@bodhiapp/bodhi-js 0.0.1 → 0.0.3
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/bodhi-web.cjs.js +1 -749
- package/dist/bodhi-web.esm.js +267 -393
- package/package.json +2 -2
- package/dist/bodhi-web.cjs.js.map +0 -1
- package/dist/bodhi-web.esm.js.map +0 -1
package/dist/bodhi-web.esm.js
CHANGED
|
@@ -1,57 +1,37 @@
|
|
|
1
|
-
import { DirectClientBase, STORAGE_PREFIXES, generateCodeVerifier, generateCodeChallenge, isApiResultOperationError, isApiResultSuccess, createStorageKeys, EXTENSION_STATE_NOT_INITIALIZED, Logger, createOAuthEndpoints, NOOP_STATE_CALLBACK, EXTENSION_STATE_NOT_FOUND, PENDING_EXTENSION_READY, BACKEND_SERVER_NOT_REACHABLE, extractUserInfo, refreshAccessToken, createOperationError, backendServerNotReady, SERVER_ERROR_CODES, createApiError, BaseFacadeClient } from "@bodhiapp/bodhi-js-core";
|
|
2
|
-
class
|
|
3
|
-
constructor(
|
|
4
|
-
super({ ...
|
|
5
|
-
this.redirectUri = config.redirectUri;
|
|
1
|
+
import { DirectClientBase as C, STORAGE_PREFIXES as f, generateCodeVerifier as g, generateCodeChallenge as y, isApiResultOperationError as T, isApiResultSuccess as E, createStorageKeys as x, EXTENSION_STATE_NOT_INITIALIZED as _, Logger as R, createOAuthEndpoints as A, NOOP_STATE_CALLBACK as k, EXTENSION_STATE_NOT_FOUND as v, PENDING_EXTENSION_READY as O, BACKEND_SERVER_NOT_REACHABLE as d, extractUserInfo as I, refreshAccessToken as b, createOperationError as u, backendServerNotReady as S, SERVER_ERROR_CODES as P, createApiError as U, BaseFacadeClient as N } from "@bodhiapp/bodhi-js-core";
|
|
2
|
+
class L extends C {
|
|
3
|
+
constructor(e, t) {
|
|
4
|
+
super({ ...e, storagePrefix: f.DIRECT }, "DirectWebClient", t), this.redirectUri = e.redirectUri;
|
|
6
5
|
}
|
|
7
6
|
// ============================================================================
|
|
8
7
|
// Authentication (Browser Redirect OAuth)
|
|
9
8
|
// ============================================================================
|
|
10
9
|
async login() {
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
localStorage.
|
|
21
|
-
|
|
22
|
-
const authUrl = new URL(this.authEndpoints.authorize);
|
|
23
|
-
authUrl.searchParams.set("client_id", this.authClientId);
|
|
24
|
-
authUrl.searchParams.set("response_type", "code");
|
|
25
|
-
authUrl.searchParams.set("redirect_uri", this.redirectUri);
|
|
26
|
-
authUrl.searchParams.set("scope", fullScope);
|
|
27
|
-
authUrl.searchParams.set("code_challenge", codeChallenge);
|
|
28
|
-
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
29
|
-
authUrl.searchParams.set("state", state);
|
|
30
|
-
window.location.href = authUrl.toString();
|
|
31
|
-
throw new Error("Redirect initiated");
|
|
32
|
-
}
|
|
33
|
-
async handleOAuthCallback(code, state) {
|
|
34
|
-
const storedState = localStorage.getItem(this.storageKeys.STATE);
|
|
35
|
-
if (!storedState || storedState !== state) {
|
|
10
|
+
const e = await this.getAuthState();
|
|
11
|
+
if (e.isLoggedIn)
|
|
12
|
+
return e;
|
|
13
|
+
const t = await this.requestResourceAccess(), r = `openid profile email roles ${this.userScope} ${t}`, s = g(), i = await y(s), o = g();
|
|
14
|
+
localStorage.setItem(this.storageKeys.CODE_VERIFIER, s), localStorage.setItem(this.storageKeys.STATE, o);
|
|
15
|
+
const a = new URL(this.authEndpoints.authorize);
|
|
16
|
+
throw a.searchParams.set("client_id", this.authClientId), a.searchParams.set("response_type", "code"), a.searchParams.set("redirect_uri", this.redirectUri), a.searchParams.set("scope", r), a.searchParams.set("code_challenge", i), a.searchParams.set("code_challenge_method", "S256"), a.searchParams.set("state", o), window.location.href = a.toString(), new Error("Redirect initiated");
|
|
17
|
+
}
|
|
18
|
+
async handleOAuthCallback(e, t) {
|
|
19
|
+
const r = localStorage.getItem(this.storageKeys.STATE);
|
|
20
|
+
if (!r || r !== t)
|
|
36
21
|
throw new Error("Invalid state parameter - possible CSRF attack");
|
|
37
|
-
|
|
38
|
-
await this.
|
|
39
|
-
|
|
40
|
-
localStorage.removeItem(this.storageKeys.STATE);
|
|
41
|
-
const authState = await this.getAuthState();
|
|
42
|
-
if (!authState.isLoggedIn) {
|
|
22
|
+
await this.exchangeCodeForTokens(e), localStorage.removeItem(this.storageKeys.CODE_VERIFIER), localStorage.removeItem(this.storageKeys.STATE);
|
|
23
|
+
const s = await this.getAuthState();
|
|
24
|
+
if (!s.isLoggedIn)
|
|
43
25
|
throw new Error("Login failed");
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.setAuthState(result);
|
|
47
|
-
return result;
|
|
26
|
+
const i = s;
|
|
27
|
+
return this.setAuthState(i), i;
|
|
48
28
|
}
|
|
49
29
|
async logout() {
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
30
|
+
const e = localStorage.getItem(this.storageKeys.REFRESH_TOKEN);
|
|
31
|
+
if (e)
|
|
52
32
|
try {
|
|
53
|
-
const
|
|
54
|
-
token:
|
|
33
|
+
const r = new URLSearchParams({
|
|
34
|
+
token: e,
|
|
55
35
|
client_id: this.authClientId,
|
|
56
36
|
token_type_hint: "refresh_token"
|
|
57
37
|
});
|
|
@@ -60,126 +40,102 @@ class DirectWebClient extends DirectClientBase {
|
|
|
60
40
|
headers: {
|
|
61
41
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
62
42
|
},
|
|
63
|
-
body:
|
|
43
|
+
body: r
|
|
64
44
|
});
|
|
65
|
-
} catch (
|
|
66
|
-
this.logger.warn("Token revocation failed:",
|
|
45
|
+
} catch (r) {
|
|
46
|
+
this.logger.warn("Token revocation failed:", r);
|
|
67
47
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
localStorage.removeItem(this.storageKeys.EXPIRES_AT);
|
|
72
|
-
localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);
|
|
73
|
-
const result = {
|
|
74
|
-
isLoggedIn: false
|
|
48
|
+
localStorage.removeItem(this.storageKeys.ACCESS_TOKEN), localStorage.removeItem(this.storageKeys.REFRESH_TOKEN), localStorage.removeItem(this.storageKeys.EXPIRES_AT), localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);
|
|
49
|
+
const t = {
|
|
50
|
+
isLoggedIn: !1
|
|
75
51
|
};
|
|
76
|
-
this.setAuthState(
|
|
77
|
-
return result;
|
|
52
|
+
return this.setAuthState(t), t;
|
|
78
53
|
}
|
|
79
54
|
// ============================================================================
|
|
80
55
|
// OAuth Helper Methods
|
|
81
56
|
// ============================================================================
|
|
82
57
|
async requestResourceAccess() {
|
|
83
|
-
const
|
|
58
|
+
const e = await this.sendApiRequest(
|
|
84
59
|
"POST",
|
|
85
60
|
"/bodhi/v1/apps/request-access",
|
|
86
61
|
{ app_client_id: this.authClientId },
|
|
87
62
|
{},
|
|
88
|
-
|
|
63
|
+
!1
|
|
89
64
|
);
|
|
90
|
-
if (
|
|
65
|
+
if (T(e))
|
|
91
66
|
throw new Error("Failed to get resource access scope from server");
|
|
92
|
-
|
|
93
|
-
if (!isApiResultSuccess(response)) {
|
|
67
|
+
if (!E(e))
|
|
94
68
|
throw new Error("Failed to get resource access scope from server: API error");
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
localStorage.setItem(this.storageKeys.RESOURCE_SCOPE, scope);
|
|
98
|
-
return scope;
|
|
69
|
+
const t = e.body.scope;
|
|
70
|
+
return localStorage.setItem(this.storageKeys.RESOURCE_SCOPE, t), t;
|
|
99
71
|
}
|
|
100
|
-
async exchangeCodeForTokens(
|
|
101
|
-
const
|
|
102
|
-
if (!
|
|
72
|
+
async exchangeCodeForTokens(e) {
|
|
73
|
+
const t = localStorage.getItem(this.storageKeys.CODE_VERIFIER);
|
|
74
|
+
if (!t)
|
|
103
75
|
throw new Error("Code verifier not found");
|
|
104
|
-
|
|
105
|
-
const response = await fetch(this.authEndpoints.token, {
|
|
76
|
+
const r = await fetch(this.authEndpoints.token, {
|
|
106
77
|
method: "POST",
|
|
107
78
|
headers: {
|
|
108
79
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
109
80
|
},
|
|
110
81
|
body: new URLSearchParams({
|
|
111
82
|
grant_type: "authorization_code",
|
|
112
|
-
code,
|
|
83
|
+
code: e,
|
|
113
84
|
redirect_uri: this.redirectUri,
|
|
114
85
|
client_id: this.authClientId,
|
|
115
|
-
code_verifier:
|
|
86
|
+
code_verifier: t
|
|
116
87
|
})
|
|
117
88
|
});
|
|
118
|
-
if (!
|
|
119
|
-
const
|
|
120
|
-
throw new Error(`Token exchange failed: ${
|
|
121
|
-
}
|
|
122
|
-
const tokens = await response.json();
|
|
123
|
-
localStorage.setItem(this.storageKeys.ACCESS_TOKEN, tokens.access_token);
|
|
124
|
-
if (tokens.refresh_token) {
|
|
125
|
-
localStorage.setItem(this.storageKeys.REFRESH_TOKEN, tokens.refresh_token);
|
|
89
|
+
if (!r.ok) {
|
|
90
|
+
const i = await r.text();
|
|
91
|
+
throw new Error(`Token exchange failed: ${r.status} ${i}`);
|
|
126
92
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
93
|
+
const s = await r.json();
|
|
94
|
+
if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, s.access_token), s.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, s.refresh_token), s.expires_in) {
|
|
95
|
+
const i = Date.now() + s.expires_in * 1e3;
|
|
96
|
+
localStorage.setItem(this.storageKeys.EXPIRES_AT, i.toString());
|
|
130
97
|
}
|
|
131
98
|
}
|
|
132
99
|
// ============================================================================
|
|
133
100
|
// Storage Implementation (localStorage)
|
|
134
101
|
// ============================================================================
|
|
135
|
-
async _storageGet(
|
|
136
|
-
return localStorage.getItem(
|
|
102
|
+
async _storageGet(e) {
|
|
103
|
+
return localStorage.getItem(e);
|
|
137
104
|
}
|
|
138
|
-
async _storageSet(
|
|
139
|
-
Object.entries(
|
|
140
|
-
localStorage.setItem(
|
|
105
|
+
async _storageSet(e) {
|
|
106
|
+
Object.entries(e).forEach(([t, r]) => {
|
|
107
|
+
localStorage.setItem(t, String(r));
|
|
141
108
|
});
|
|
142
109
|
}
|
|
143
|
-
async _storageRemove(
|
|
144
|
-
|
|
110
|
+
async _storageRemove(e) {
|
|
111
|
+
e.forEach((t) => localStorage.removeItem(t));
|
|
145
112
|
}
|
|
146
113
|
_getRedirectUri() {
|
|
147
114
|
return this.redirectUri;
|
|
148
115
|
}
|
|
149
116
|
}
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
constructor(authClientId, config, onStateChange) {
|
|
155
|
-
this.state = EXTENSION_STATE_NOT_INITIALIZED;
|
|
156
|
-
this.bodhiext = null;
|
|
157
|
-
this.refreshPromise = null;
|
|
158
|
-
this.logger = new Logger("WindowBodhiextClient", config.logLevel);
|
|
159
|
-
this.authClientId = authClientId;
|
|
160
|
-
this.config = config;
|
|
161
|
-
this.authEndpoints = createOAuthEndpoints(this.config.authServerUrl);
|
|
162
|
-
this.onStateChange = onStateChange ?? NOOP_STATE_CALLBACK;
|
|
117
|
+
const K = 500, F = 5e3, n = x(f.WEB);
|
|
118
|
+
class D {
|
|
119
|
+
constructor(e, t, r) {
|
|
120
|
+
this.state = _, this.bodhiext = null, this.refreshPromise = null, this.logger = new R("WindowBodhiextClient", t.logLevel), this.authClientId = e, this.config = t, this.authEndpoints = A(this.config.authServerUrl), this.onStateChange = r ?? k;
|
|
163
121
|
}
|
|
164
122
|
/**
|
|
165
123
|
* Set client state and notify callback
|
|
166
124
|
*/
|
|
167
|
-
setState(
|
|
168
|
-
this.state =
|
|
169
|
-
this.logger.info(`{state: ${JSON.stringify(newState)}} - Setting client state`);
|
|
170
|
-
this.onStateChange({ type: "client-state", state: newState });
|
|
125
|
+
setState(e) {
|
|
126
|
+
this.state = e, this.logger.info(`{state: ${JSON.stringify(e)}} - Setting client state`), this.onStateChange({ type: "client-state", state: e });
|
|
171
127
|
}
|
|
172
128
|
/**
|
|
173
129
|
* Set auth state and notify callback
|
|
174
130
|
*/
|
|
175
|
-
setAuthState(
|
|
176
|
-
this.onStateChange({ type: "auth-state", state:
|
|
131
|
+
setAuthState(e) {
|
|
132
|
+
this.onStateChange({ type: "auth-state", state: e });
|
|
177
133
|
}
|
|
178
134
|
/**
|
|
179
135
|
* Set or update the state change callback
|
|
180
136
|
*/
|
|
181
|
-
setStateCallback(
|
|
182
|
-
this.onStateChange =
|
|
137
|
+
setStateCallback(e) {
|
|
138
|
+
this.onStateChange = e;
|
|
183
139
|
}
|
|
184
140
|
// ============================================================================
|
|
185
141
|
// Extension Communication
|
|
@@ -189,68 +145,58 @@ class WindowBodhiextClient {
|
|
|
189
145
|
* @throws Error if client not initialized
|
|
190
146
|
*/
|
|
191
147
|
ensureBodhiext() {
|
|
192
|
-
if (!this.bodhiext && window.bodhiext)
|
|
193
|
-
this.logger.info("Acquiring window.bodhiext reference");
|
|
194
|
-
this.bodhiext = window.bodhiext;
|
|
195
|
-
}
|
|
196
|
-
if (!this.bodhiext) {
|
|
148
|
+
if (!this.bodhiext && window.bodhiext && (this.logger.info("Acquiring window.bodhiext reference"), this.bodhiext = window.bodhiext), !this.bodhiext)
|
|
197
149
|
throw new Error("Client not initialized");
|
|
198
|
-
}
|
|
199
150
|
}
|
|
200
151
|
/**
|
|
201
152
|
* Send extension request via window.bodhiext.sendExtRequest
|
|
202
153
|
*/
|
|
203
|
-
async sendExtRequest(
|
|
204
|
-
this.ensureBodhiext();
|
|
205
|
-
return this.bodhiext.sendExtRequest(action, params);
|
|
154
|
+
async sendExtRequest(e, t) {
|
|
155
|
+
return this.ensureBodhiext(), this.bodhiext.sendExtRequest(e, t);
|
|
206
156
|
}
|
|
207
157
|
/**
|
|
208
158
|
* Send API message via window.bodhiext.sendApiRequest
|
|
209
159
|
* Converts ApiResponse to ApiResponseResult
|
|
210
160
|
*/
|
|
211
|
-
async sendApiRequest(
|
|
161
|
+
async sendApiRequest(e, t, r, s, i) {
|
|
212
162
|
try {
|
|
213
163
|
this.ensureBodhiext();
|
|
214
|
-
} catch (
|
|
164
|
+
} catch (o) {
|
|
215
165
|
return {
|
|
216
166
|
error: {
|
|
217
|
-
message:
|
|
167
|
+
message: o instanceof Error ? o.message : String(o),
|
|
218
168
|
type: "extension_error"
|
|
219
169
|
}
|
|
220
170
|
};
|
|
221
171
|
}
|
|
222
172
|
try {
|
|
223
|
-
let
|
|
224
|
-
if (
|
|
225
|
-
const
|
|
226
|
-
if (!
|
|
173
|
+
let o = s || {};
|
|
174
|
+
if (i) {
|
|
175
|
+
const h = await this._getAccessTokenRaw();
|
|
176
|
+
if (!h)
|
|
227
177
|
return {
|
|
228
178
|
error: {
|
|
229
179
|
message: "Not authenticated. Please log in first.",
|
|
230
180
|
type: "extension_error"
|
|
231
181
|
}
|
|
232
182
|
};
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
Authorization: `Bearer ${accessToken}`
|
|
183
|
+
o = {
|
|
184
|
+
...o,
|
|
185
|
+
Authorization: `Bearer ${h}`
|
|
237
186
|
};
|
|
238
187
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
188
|
+
return await this.bodhiext.sendApiRequest(
|
|
189
|
+
e,
|
|
190
|
+
t,
|
|
191
|
+
r,
|
|
192
|
+
o
|
|
244
193
|
);
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const errorObj = e == null ? void 0 : e.error;
|
|
248
|
-
const message = (errorObj == null ? void 0 : errorObj.message) ?? (e instanceof Error ? e.message : String(e));
|
|
249
|
-
const errorType = (errorObj == null ? void 0 : errorObj.type) || "extension_error";
|
|
194
|
+
} catch (o) {
|
|
195
|
+
const a = o == null ? void 0 : o.error, h = (a == null ? void 0 : a.message) ?? (o instanceof Error ? o.message : String(o)), c = (a == null ? void 0 : a.type) || "extension_error";
|
|
250
196
|
return {
|
|
251
197
|
error: {
|
|
252
|
-
message,
|
|
253
|
-
type:
|
|
198
|
+
message: h,
|
|
199
|
+
type: c
|
|
254
200
|
}
|
|
255
201
|
};
|
|
256
202
|
}
|
|
@@ -274,61 +220,47 @@ class WindowBodhiextClient {
|
|
|
274
220
|
* Note: Web mode uses stateless discovery (always polls for window.bodhiext)
|
|
275
221
|
* No extensionId storage/restoration needed - window.bodhiext handle is ephemeral
|
|
276
222
|
*/
|
|
277
|
-
async init(
|
|
278
|
-
var
|
|
279
|
-
if (!
|
|
280
|
-
this.logger.info("No testConnection or selectedConnection, returning not-initialized state");
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if (this.bodhiext && !params.testConnection) {
|
|
284
|
-
this.logger.debug("Already have bodhiext handle, skipping polling");
|
|
285
|
-
return this.state;
|
|
286
|
-
}
|
|
223
|
+
async init(e = {}) {
|
|
224
|
+
var s, i, o, a;
|
|
225
|
+
if (!e.testConnection && !e.selectedConnection)
|
|
226
|
+
return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"), _;
|
|
227
|
+
if (this.bodhiext && !e.testConnection)
|
|
228
|
+
return this.logger.debug("Already have bodhiext handle, skipping polling"), this.state;
|
|
287
229
|
if (!this.bodhiext) {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const found = await new Promise((resolve) => {
|
|
292
|
-
const check = () => {
|
|
230
|
+
const h = e.timeoutMs ?? ((i = (s = this.config.initParams) == null ? void 0 : s.extension) == null ? void 0 : i.timeoutMs) ?? F, c = e.intervalMs ?? ((a = (o = this.config.initParams) == null ? void 0 : o.extension) == null ? void 0 : a.intervalMs) ?? K, l = Date.now();
|
|
231
|
+
if (!await new Promise((p) => {
|
|
232
|
+
const w = () => {
|
|
293
233
|
if (window.bodhiext) {
|
|
294
|
-
this.bodhiext = window.bodhiext;
|
|
295
|
-
resolve(true);
|
|
234
|
+
this.bodhiext = window.bodhiext, p(!0);
|
|
296
235
|
return;
|
|
297
236
|
}
|
|
298
|
-
if (Date.now() -
|
|
299
|
-
|
|
237
|
+
if (Date.now() - l >= h) {
|
|
238
|
+
p(!1);
|
|
300
239
|
return;
|
|
301
240
|
}
|
|
302
|
-
setTimeout(
|
|
241
|
+
setTimeout(w, c);
|
|
303
242
|
};
|
|
304
|
-
|
|
305
|
-
})
|
|
306
|
-
|
|
307
|
-
this.logger.warn(`Extension discovery timed out`);
|
|
308
|
-
this.setState(EXTENSION_STATE_NOT_FOUND);
|
|
309
|
-
return this.state;
|
|
310
|
-
}
|
|
243
|
+
w();
|
|
244
|
+
}))
|
|
245
|
+
return this.logger.warn("Extension discovery timed out"), this.setState(v), this.state;
|
|
311
246
|
}
|
|
312
|
-
const
|
|
313
|
-
this.logger.info(`Extension discovered: ${
|
|
314
|
-
const
|
|
247
|
+
const t = await this.bodhiext.getExtensionId();
|
|
248
|
+
this.logger.info(`Extension discovered: ${t}`);
|
|
249
|
+
const r = {
|
|
315
250
|
type: "extension",
|
|
316
251
|
extension: "ready",
|
|
317
|
-
extensionId,
|
|
318
|
-
server:
|
|
252
|
+
extensionId: t,
|
|
253
|
+
server: O
|
|
319
254
|
};
|
|
320
|
-
if (
|
|
255
|
+
if (e.testConnection)
|
|
321
256
|
try {
|
|
322
|
-
const
|
|
323
|
-
this.setState({ ...
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.logger.error(`Failed to get server state:`, error);
|
|
327
|
-
this.setState({ ...state, server: BACKEND_SERVER_NOT_REACHABLE });
|
|
257
|
+
const h = await this.getServerState();
|
|
258
|
+
this.setState({ ...r, server: h }), this.logger.info(`Server connectivity tested: ${h.status}`);
|
|
259
|
+
} catch (h) {
|
|
260
|
+
this.logger.error("Failed to get server state:", h), this.setState({ ...r, server: d });
|
|
328
261
|
}
|
|
329
|
-
|
|
330
|
-
this.setState(
|
|
331
|
-
}
|
|
262
|
+
else
|
|
263
|
+
this.setState(r);
|
|
332
264
|
return this.state;
|
|
333
265
|
}
|
|
334
266
|
// ============================================================================
|
|
@@ -340,45 +272,35 @@ class WindowBodhiextClient {
|
|
|
340
272
|
*/
|
|
341
273
|
async requestResourceAccess() {
|
|
342
274
|
this.ensureBodhiext();
|
|
343
|
-
const
|
|
275
|
+
const e = await this.bodhiext.sendApiRequest("POST", "/bodhi/v1/apps/request-access", {
|
|
344
276
|
app_client_id: this.authClientId
|
|
345
277
|
});
|
|
346
|
-
if (!
|
|
278
|
+
if (!E(e))
|
|
347
279
|
throw new Error("Failed to get resource access scope: API error");
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
localStorage.setItem(STORAGE_KEYS.RESOURCE_SCOPE, scope);
|
|
351
|
-
return scope;
|
|
280
|
+
const t = e.body.scope;
|
|
281
|
+
return localStorage.setItem(n.RESOURCE_SCOPE, t), t;
|
|
352
282
|
}
|
|
353
283
|
/**
|
|
354
284
|
* Login via browser redirect OAuth2 + PKCE flow
|
|
355
285
|
* @returns AuthLoggedIn (though in practice, this redirects and never returns)
|
|
356
286
|
*/
|
|
357
287
|
async login() {
|
|
358
|
-
const
|
|
359
|
-
if (
|
|
360
|
-
return
|
|
361
|
-
}
|
|
288
|
+
const e = await this.getAuthState();
|
|
289
|
+
if (e.isLoggedIn)
|
|
290
|
+
return e;
|
|
362
291
|
this.ensureBodhiext();
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
const state = generateCodeVerifier();
|
|
367
|
-
localStorage.setItem(STORAGE_KEYS.CODE_VERIFIER, codeVerifier);
|
|
368
|
-
localStorage.setItem(STORAGE_KEYS.STATE, state);
|
|
369
|
-
const scopes = ["openid", "profile", "email", "roles", this.config.userScope, resourceScope];
|
|
370
|
-
const params = new URLSearchParams({
|
|
292
|
+
const t = await this.requestResourceAccess(), r = g(), s = await y(r), i = g();
|
|
293
|
+
localStorage.setItem(n.CODE_VERIFIER, r), localStorage.setItem(n.STATE, i);
|
|
294
|
+
const o = ["openid", "profile", "email", "roles", this.config.userScope, t], a = new URLSearchParams({
|
|
371
295
|
response_type: "code",
|
|
372
296
|
client_id: this.authClientId,
|
|
373
297
|
redirect_uri: this.config.redirectUri,
|
|
374
|
-
scope:
|
|
375
|
-
state,
|
|
376
|
-
code_challenge:
|
|
298
|
+
scope: o.join(" "),
|
|
299
|
+
state: i,
|
|
300
|
+
code_challenge: s,
|
|
377
301
|
code_challenge_method: "S256"
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
window.location.href = authUrl;
|
|
381
|
-
return new Promise(() => {
|
|
302
|
+
}), h = `${this.authEndpoints.authorize}?${a}`;
|
|
303
|
+
return window.location.href = h, new Promise(() => {
|
|
382
304
|
});
|
|
383
305
|
}
|
|
384
306
|
/**
|
|
@@ -386,58 +308,46 @@ class WindowBodhiextClient {
|
|
|
386
308
|
* Should be called from callback page with extracted URL params
|
|
387
309
|
* @returns AuthLoggedIn with login state and user info
|
|
388
310
|
*/
|
|
389
|
-
async handleOAuthCallback(
|
|
390
|
-
const
|
|
391
|
-
if (!
|
|
311
|
+
async handleOAuthCallback(e, t) {
|
|
312
|
+
const r = localStorage.getItem(n.STATE);
|
|
313
|
+
if (!r || r !== t)
|
|
392
314
|
throw new Error("Invalid state parameter - possible CSRF attack");
|
|
393
|
-
|
|
394
|
-
await this.
|
|
395
|
-
|
|
396
|
-
localStorage.removeItem(STORAGE_KEYS.STATE);
|
|
397
|
-
const authState = await this.getAuthState();
|
|
398
|
-
if (!authState.isLoggedIn) {
|
|
315
|
+
await this.exchangeCodeForTokens(e), localStorage.removeItem(n.CODE_VERIFIER), localStorage.removeItem(n.STATE);
|
|
316
|
+
const s = await this.getAuthState();
|
|
317
|
+
if (!s.isLoggedIn)
|
|
399
318
|
throw new Error("Login failed");
|
|
400
|
-
|
|
401
|
-
this.setAuthState(authState);
|
|
402
|
-
return authState;
|
|
319
|
+
return this.setAuthState(s), s;
|
|
403
320
|
}
|
|
404
321
|
/**
|
|
405
322
|
* Exchange authorization code for tokens
|
|
406
323
|
*/
|
|
407
|
-
async exchangeCodeForTokens(
|
|
408
|
-
const
|
|
409
|
-
if (!
|
|
324
|
+
async exchangeCodeForTokens(e) {
|
|
325
|
+
const t = localStorage.getItem(n.CODE_VERIFIER);
|
|
326
|
+
if (!t)
|
|
410
327
|
throw new Error("Code verifier not found");
|
|
411
|
-
|
|
412
|
-
const params = new URLSearchParams({
|
|
328
|
+
const r = new URLSearchParams({
|
|
413
329
|
grant_type: "authorization_code",
|
|
414
330
|
client_id: this.authClientId,
|
|
415
|
-
code,
|
|
331
|
+
code: e,
|
|
416
332
|
redirect_uri: this.config.redirectUri,
|
|
417
|
-
code_verifier:
|
|
418
|
-
})
|
|
419
|
-
const response = await fetch(this.authEndpoints.token, {
|
|
333
|
+
code_verifier: t
|
|
334
|
+
}), s = await fetch(this.authEndpoints.token, {
|
|
420
335
|
method: "POST",
|
|
421
336
|
headers: {
|
|
422
337
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
423
338
|
},
|
|
424
|
-
body:
|
|
339
|
+
body: r
|
|
425
340
|
});
|
|
426
|
-
if (!
|
|
427
|
-
const
|
|
428
|
-
throw new Error(`Token exchange failed: ${
|
|
341
|
+
if (!s.ok) {
|
|
342
|
+
const o = await s.text();
|
|
343
|
+
throw new Error(`Token exchange failed: ${s.status} ${o}`);
|
|
429
344
|
}
|
|
430
|
-
const
|
|
431
|
-
if (!
|
|
345
|
+
const i = await s.json();
|
|
346
|
+
if (!i.access_token)
|
|
432
347
|
throw new Error("No access token received");
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, tokenData.refresh_token);
|
|
437
|
-
}
|
|
438
|
-
if (tokenData.expires_in) {
|
|
439
|
-
const expiresAt = Date.now() + tokenData.expires_in * 1e3;
|
|
440
|
-
localStorage.setItem(STORAGE_KEYS.EXPIRES_AT, expiresAt.toString());
|
|
348
|
+
if (localStorage.setItem(n.ACCESS_TOKEN, i.access_token), i.refresh_token && localStorage.setItem(n.REFRESH_TOKEN, i.refresh_token), i.expires_in) {
|
|
349
|
+
const o = Date.now() + i.expires_in * 1e3;
|
|
350
|
+
localStorage.setItem(n.EXPIRES_AT, o.toString());
|
|
441
351
|
}
|
|
442
352
|
}
|
|
443
353
|
/**
|
|
@@ -445,11 +355,11 @@ class WindowBodhiextClient {
|
|
|
445
355
|
* @returns AuthLoggedOut with logged out state
|
|
446
356
|
*/
|
|
447
357
|
async logout() {
|
|
448
|
-
const
|
|
449
|
-
if (
|
|
358
|
+
const e = localStorage.getItem(n.REFRESH_TOKEN);
|
|
359
|
+
if (e)
|
|
450
360
|
try {
|
|
451
|
-
const
|
|
452
|
-
token:
|
|
361
|
+
const r = new URLSearchParams({
|
|
362
|
+
token: e,
|
|
453
363
|
client_id: this.authClientId,
|
|
454
364
|
token_type_hint: "refresh_token"
|
|
455
365
|
});
|
|
@@ -458,38 +368,28 @@ class WindowBodhiextClient {
|
|
|
458
368
|
headers: {
|
|
459
369
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
460
370
|
},
|
|
461
|
-
body:
|
|
371
|
+
body: r
|
|
462
372
|
});
|
|
463
|
-
} catch (
|
|
464
|
-
this.logger.warn("Token revocation failed:",
|
|
373
|
+
} catch (r) {
|
|
374
|
+
this.logger.warn("Token revocation failed:", r);
|
|
465
375
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
localStorage.removeItem(STORAGE_KEYS.EXPIRES_AT);
|
|
470
|
-
localStorage.removeItem(STORAGE_KEYS.CODE_VERIFIER);
|
|
471
|
-
localStorage.removeItem(STORAGE_KEYS.STATE);
|
|
472
|
-
localStorage.removeItem(STORAGE_KEYS.RESOURCE_SCOPE);
|
|
473
|
-
const result = {
|
|
474
|
-
isLoggedIn: false
|
|
376
|
+
localStorage.removeItem(n.ACCESS_TOKEN), localStorage.removeItem(n.REFRESH_TOKEN), localStorage.removeItem(n.EXPIRES_AT), localStorage.removeItem(n.CODE_VERIFIER), localStorage.removeItem(n.STATE), localStorage.removeItem(n.RESOURCE_SCOPE);
|
|
377
|
+
const t = {
|
|
378
|
+
isLoggedIn: !1
|
|
475
379
|
};
|
|
476
|
-
this.setAuthState(
|
|
477
|
-
return result;
|
|
380
|
+
return this.setAuthState(t), t;
|
|
478
381
|
}
|
|
479
382
|
/**
|
|
480
383
|
* Get current authentication state
|
|
481
384
|
*/
|
|
482
385
|
async getAuthState() {
|
|
483
|
-
const
|
|
484
|
-
if (!
|
|
485
|
-
return { isLoggedIn:
|
|
486
|
-
}
|
|
386
|
+
const e = await this._getAccessTokenRaw();
|
|
387
|
+
if (!e)
|
|
388
|
+
return { isLoggedIn: !1 };
|
|
487
389
|
try {
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
this.logger.error("Failed to parse token:", error);
|
|
492
|
-
return { isLoggedIn: false };
|
|
390
|
+
return { isLoggedIn: !0, userInfo: I(e), accessToken: e };
|
|
391
|
+
} catch (t) {
|
|
392
|
+
return this.logger.error("Failed to parse token:", t), { isLoggedIn: !1 };
|
|
493
393
|
}
|
|
494
394
|
}
|
|
495
395
|
/**
|
|
@@ -497,33 +397,26 @@ class WindowBodhiextClient {
|
|
|
497
397
|
* Returns null if not logged in or token expired
|
|
498
398
|
*/
|
|
499
399
|
async _getAccessTokenRaw() {
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
if (!accessToken) {
|
|
400
|
+
const e = localStorage.getItem(n.ACCESS_TOKEN), t = localStorage.getItem(n.EXPIRES_AT);
|
|
401
|
+
if (!e)
|
|
503
402
|
return null;
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
if (refreshToken) {
|
|
510
|
-
return this._tryRefreshToken(refreshToken);
|
|
511
|
-
}
|
|
512
|
-
return null;
|
|
403
|
+
if (t) {
|
|
404
|
+
const r = parseInt(t, 10);
|
|
405
|
+
if (Date.now() >= r - 5 * 1e3) {
|
|
406
|
+
const s = localStorage.getItem(n.REFRESH_TOKEN);
|
|
407
|
+
return s ? this._tryRefreshToken(s) : null;
|
|
513
408
|
}
|
|
514
409
|
}
|
|
515
|
-
return
|
|
410
|
+
return e;
|
|
516
411
|
}
|
|
517
412
|
/**
|
|
518
413
|
* Try to refresh access token using refresh token
|
|
519
414
|
* Race condition prevention: Returns existing promise if refresh already in progress
|
|
520
415
|
*/
|
|
521
|
-
async _tryRefreshToken(
|
|
522
|
-
if (this.refreshPromise)
|
|
523
|
-
this.logger.debug("Refresh already in progress, returning existing promise");
|
|
524
|
-
|
|
525
|
-
}
|
|
526
|
-
this.refreshPromise = this._doRefreshToken(refreshToken);
|
|
416
|
+
async _tryRefreshToken(e) {
|
|
417
|
+
if (this.refreshPromise)
|
|
418
|
+
return this.logger.debug("Refresh already in progress, returning existing promise"), this.refreshPromise;
|
|
419
|
+
this.refreshPromise = this._doRefreshToken(e);
|
|
527
420
|
try {
|
|
528
421
|
return await this.refreshPromise;
|
|
529
422
|
} finally {
|
|
@@ -533,30 +426,27 @@ class WindowBodhiextClient {
|
|
|
533
426
|
/**
|
|
534
427
|
* Perform the actual token refresh
|
|
535
428
|
*/
|
|
536
|
-
async _doRefreshToken(
|
|
429
|
+
async _doRefreshToken(e) {
|
|
537
430
|
this.logger.debug("Refreshing access token");
|
|
538
431
|
try {
|
|
539
|
-
const
|
|
432
|
+
const t = await b(
|
|
540
433
|
this.authEndpoints.token,
|
|
541
|
-
|
|
434
|
+
e,
|
|
542
435
|
this.authClientId
|
|
543
436
|
);
|
|
544
|
-
if (
|
|
545
|
-
this._storeRefreshedTokens(
|
|
546
|
-
const
|
|
547
|
-
this.setAuthState({
|
|
548
|
-
isLoggedIn:
|
|
549
|
-
userInfo,
|
|
550
|
-
accessToken:
|
|
551
|
-
});
|
|
552
|
-
this.logger.info("Token refreshed successfully");
|
|
553
|
-
return tokens.access_token;
|
|
437
|
+
if (t) {
|
|
438
|
+
this._storeRefreshedTokens(t);
|
|
439
|
+
const r = I(t.access_token);
|
|
440
|
+
return this.setAuthState({
|
|
441
|
+
isLoggedIn: !0,
|
|
442
|
+
userInfo: r,
|
|
443
|
+
accessToken: t.access_token
|
|
444
|
+
}), this.logger.info("Token refreshed successfully"), t.access_token;
|
|
554
445
|
}
|
|
555
|
-
} catch (
|
|
556
|
-
this.logger.warn("Token refresh failed:",
|
|
446
|
+
} catch (t) {
|
|
447
|
+
this.logger.warn("Token refresh failed:", t);
|
|
557
448
|
}
|
|
558
|
-
this.logger.warn("Token refresh failed, keeping tokens for manual retry")
|
|
559
|
-
throw createOperationError(
|
|
449
|
+
throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), u(
|
|
560
450
|
"Access token expired and unable to refresh. Try logging out and logging in again.",
|
|
561
451
|
"token_refresh_failed"
|
|
562
452
|
);
|
|
@@ -564,13 +454,9 @@ class WindowBodhiextClient {
|
|
|
564
454
|
/**
|
|
565
455
|
* Store refreshed tokens
|
|
566
456
|
*/
|
|
567
|
-
_storeRefreshedTokens(
|
|
568
|
-
const
|
|
569
|
-
localStorage.setItem(
|
|
570
|
-
localStorage.setItem(STORAGE_KEYS.EXPIRES_AT, String(expiresAt));
|
|
571
|
-
if (tokens.refresh_token) {
|
|
572
|
-
localStorage.setItem(STORAGE_KEYS.REFRESH_TOKEN, tokens.refresh_token);
|
|
573
|
-
}
|
|
457
|
+
_storeRefreshedTokens(e) {
|
|
458
|
+
const t = Date.now() + e.expires_in * 1e3;
|
|
459
|
+
localStorage.setItem(n.ACCESS_TOKEN, e.access_token), localStorage.setItem(n.EXPIRES_AT, String(t)), e.refresh_token && localStorage.setItem(n.REFRESH_TOKEN, e.refresh_token);
|
|
574
460
|
}
|
|
575
461
|
/**
|
|
576
462
|
* Ping API
|
|
@@ -587,7 +473,7 @@ class WindowBodhiextClient {
|
|
|
587
473
|
"/v1/models",
|
|
588
474
|
void 0,
|
|
589
475
|
void 0,
|
|
590
|
-
|
|
476
|
+
!0
|
|
591
477
|
);
|
|
592
478
|
}
|
|
593
479
|
/**
|
|
@@ -595,88 +481,80 @@ class WindowBodhiextClient {
|
|
|
595
481
|
* Calls /bodhi/v1/info and returns structured server state
|
|
596
482
|
*/
|
|
597
483
|
async getServerState() {
|
|
598
|
-
const
|
|
599
|
-
if (
|
|
600
|
-
return
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
const body = result.body;
|
|
606
|
-
switch (body.status) {
|
|
484
|
+
const e = await this.sendApiRequest("GET", "/bodhi/v1/info");
|
|
485
|
+
if (T(e))
|
|
486
|
+
return d;
|
|
487
|
+
if (!E(e))
|
|
488
|
+
return d;
|
|
489
|
+
const t = e.body;
|
|
490
|
+
switch (t.status) {
|
|
607
491
|
case "ready":
|
|
608
|
-
return { status: "ready", version:
|
|
492
|
+
return { status: "ready", version: t.version || "unknown" };
|
|
609
493
|
case "setup":
|
|
610
|
-
return
|
|
494
|
+
return S("setup", t.version || "unknown");
|
|
611
495
|
case "resource-admin":
|
|
612
|
-
return
|
|
496
|
+
return S("resource-admin", t.version || "unknown");
|
|
613
497
|
case "error":
|
|
614
|
-
return
|
|
498
|
+
return S(
|
|
615
499
|
"error",
|
|
616
|
-
|
|
617
|
-
|
|
500
|
+
t.version || "unknown",
|
|
501
|
+
t.error ? { message: t.error.message, type: t.error.type } : P.SERVER_NOT_READY
|
|
618
502
|
);
|
|
619
503
|
default:
|
|
620
|
-
return
|
|
504
|
+
return d;
|
|
621
505
|
}
|
|
622
506
|
}
|
|
623
507
|
/**
|
|
624
508
|
* Generic streaming via window.bodhiext.sendStreamRequest
|
|
625
509
|
* Wraps ReadableStream as AsyncGenerator
|
|
626
510
|
*/
|
|
627
|
-
async *stream(
|
|
511
|
+
async *stream(e, t, r, s, i = !0) {
|
|
628
512
|
this.ensureBodhiext();
|
|
629
|
-
let
|
|
630
|
-
if (
|
|
631
|
-
const
|
|
632
|
-
if (!
|
|
513
|
+
let o = s || {};
|
|
514
|
+
if (i) {
|
|
515
|
+
const c = await this._getAccessTokenRaw();
|
|
516
|
+
if (!c)
|
|
633
517
|
throw new Error("Not authenticated. Please log in first.");
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
Authorization: `Bearer ${accessToken}`
|
|
518
|
+
o = {
|
|
519
|
+
...o,
|
|
520
|
+
Authorization: `Bearer ${c}`
|
|
638
521
|
};
|
|
639
522
|
}
|
|
640
|
-
const
|
|
641
|
-
const reader = stream.getReader();
|
|
523
|
+
const h = this.bodhiext.sendStreamRequest(e, t, r, o).getReader();
|
|
642
524
|
try {
|
|
643
|
-
|
|
644
|
-
const { value, done } = await
|
|
645
|
-
if (
|
|
525
|
+
for (; ; ) {
|
|
526
|
+
const { value: c, done: l } = await h.read();
|
|
527
|
+
if (l || c != null && c.done)
|
|
646
528
|
break;
|
|
647
|
-
|
|
648
|
-
yield value.body;
|
|
529
|
+
yield c.body;
|
|
649
530
|
}
|
|
650
|
-
} catch (
|
|
651
|
-
if (
|
|
652
|
-
if ("response" in
|
|
653
|
-
const
|
|
654
|
-
throw
|
|
531
|
+
} catch (c) {
|
|
532
|
+
if (c instanceof Error) {
|
|
533
|
+
if ("response" in c) {
|
|
534
|
+
const l = c;
|
|
535
|
+
throw U(c.message, l.response.status, l.response.body);
|
|
655
536
|
}
|
|
656
|
-
|
|
657
|
-
throw createOperationError(err.message, "extension_error");
|
|
658
|
-
}
|
|
659
|
-
throw createOperationError(err.message, "extension_error");
|
|
537
|
+
throw "error" in c ? u(c.message, "extension_error") : u(c.message, "extension_error");
|
|
660
538
|
}
|
|
661
|
-
throw
|
|
539
|
+
throw c;
|
|
662
540
|
} finally {
|
|
663
|
-
|
|
541
|
+
h.releaseLock();
|
|
664
542
|
}
|
|
665
543
|
}
|
|
666
544
|
/**
|
|
667
545
|
* Chat streaming
|
|
668
546
|
*/
|
|
669
|
-
async *streamChat(
|
|
547
|
+
async *streamChat(e, t, r = !0) {
|
|
670
548
|
yield* this.stream(
|
|
671
549
|
"POST",
|
|
672
550
|
"/v1/chat/completions",
|
|
673
551
|
{
|
|
674
|
-
model,
|
|
675
|
-
messages: [{ role: "user", content:
|
|
676
|
-
stream:
|
|
552
|
+
model: e,
|
|
553
|
+
messages: [{ role: "user", content: t }],
|
|
554
|
+
stream: !0
|
|
677
555
|
},
|
|
678
556
|
void 0,
|
|
679
|
-
|
|
557
|
+
r
|
|
680
558
|
);
|
|
681
559
|
}
|
|
682
560
|
/**
|
|
@@ -703,47 +581,43 @@ class WindowBodhiextClient {
|
|
|
703
581
|
};
|
|
704
582
|
}
|
|
705
583
|
}
|
|
706
|
-
class
|
|
707
|
-
constructor(
|
|
708
|
-
const
|
|
709
|
-
redirectUri:
|
|
710
|
-
authServerUrl:
|
|
711
|
-
userScope:
|
|
712
|
-
logLevel:
|
|
713
|
-
initParams:
|
|
584
|
+
class V extends N {
|
|
585
|
+
constructor(e, t, r, s) {
|
|
586
|
+
const i = {
|
|
587
|
+
redirectUri: t.redirectUri,
|
|
588
|
+
authServerUrl: t.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
|
|
589
|
+
userScope: t.userScope || "scope_user_user",
|
|
590
|
+
logLevel: t.logLevel || "warn",
|
|
591
|
+
initParams: t.initParams
|
|
714
592
|
};
|
|
715
|
-
super(
|
|
593
|
+
super(e, i, r, s);
|
|
716
594
|
}
|
|
717
|
-
createLogger(
|
|
718
|
-
return new
|
|
595
|
+
createLogger(e) {
|
|
596
|
+
return new R("WebUIClient", e.logLevel);
|
|
719
597
|
}
|
|
720
|
-
createExtClient(
|
|
721
|
-
return new
|
|
598
|
+
createExtClient(e, t) {
|
|
599
|
+
return new D(this.authClientId, e, t);
|
|
722
600
|
}
|
|
723
|
-
createDirectClient(
|
|
724
|
-
return new
|
|
601
|
+
createDirectClient(e, t, r) {
|
|
602
|
+
return new L(
|
|
725
603
|
{
|
|
726
|
-
authClientId,
|
|
727
|
-
authServerUrl:
|
|
728
|
-
redirectUri:
|
|
729
|
-
userScope:
|
|
730
|
-
logLevel:
|
|
731
|
-
storagePrefix:
|
|
604
|
+
authClientId: e,
|
|
605
|
+
authServerUrl: t.authServerUrl,
|
|
606
|
+
redirectUri: t.redirectUri,
|
|
607
|
+
userScope: t.userScope,
|
|
608
|
+
logLevel: t.logLevel,
|
|
609
|
+
storagePrefix: f.WEB
|
|
732
610
|
},
|
|
733
|
-
|
|
611
|
+
r
|
|
734
612
|
);
|
|
735
613
|
}
|
|
736
614
|
// ============================================================================
|
|
737
615
|
// Web-specific OAuth Callback
|
|
738
616
|
// ============================================================================
|
|
739
|
-
async handleOAuthCallback(
|
|
740
|
-
|
|
741
|
-
return this.directClient.handleOAuthCallback(code, state);
|
|
742
|
-
}
|
|
743
|
-
return this.extClient.handleOAuthCallback(code, state);
|
|
617
|
+
async handleOAuthCallback(e, t) {
|
|
618
|
+
return this.connectionMode === "direct" ? this.directClient.handleOAuthCallback(e, t) : this.extClient.handleOAuthCallback(e, t);
|
|
744
619
|
}
|
|
745
620
|
}
|
|
746
621
|
export {
|
|
747
|
-
WebUIClient
|
|
622
|
+
V as WebUIClient
|
|
748
623
|
};
|
|
749
|
-
//# sourceMappingURL=bodhi-web.esm.js.map
|