@bodhiapp/bodhi-js 0.0.10 → 0.0.12

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.
@@ -125,6 +125,7 @@ export declare class WindowBodhiextClient implements IExtensionClient {
125
125
  * Perform the actual token refresh
126
126
  */
127
127
  private _doRefreshToken;
128
+ private clearAuthStorage;
128
129
  /**
129
130
  * Store refreshed tokens
130
131
  */
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("@bodhiapp/bodhi-js-core");class d extends r.DirectClientBase{constructor(e,t){const o=r.createStoragePrefixWithBasePath(e.basePath,r.STORAGE_PREFIXES.WEB_DIRECT),s={authClientId:e.authClientId,authServerUrl:e.authServerUrl,userScope:e.userScope,storagePrefix:o,logLevel:e.logLevel,loggerPrefix:"DirectWebClient"};super(s,t),this.redirectUri=e.redirectUri}async login(){const e=await this.getAuthState();if(e.status==="authenticated")return e;const t=await this.requestResourceAccess();if(r.isApiResultOperationError(t))throw r.createOperationError(t.error.message,t.error.type);if(r.isApiResultError(t)){const{message:n}=t.body.error;throw r.createOperationError(n,"auth_error")}if(!r.isApiResultSuccess(t))throw r.createOperationError(`Unexpected HTTP ${t.status}`,"auth_error");const o=t.body.scope;localStorage.setItem(this.storageKeys.RESOURCE_SCOPE,o);const s=`openid profile email roles ${this.userScope} ${o}`,a=r.generateCodeVerifier(),i=await r.generateCodeChallenge(a),h=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,a),localStorage.setItem(this.storageKeys.STATE,h);const c=new URL(this.authEndpoints.authorize);throw c.searchParams.set("client_id",this.authClientId),c.searchParams.set("response_type","code"),c.searchParams.set("redirect_uri",this.redirectUri),c.searchParams.set("scope",s),c.searchParams.set("code_challenge",i),c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("state",h),window.location.href=c.toString(),new Error("Redirect initiated")}async handleOAuthCallback(e,t){const o=localStorage.getItem(this.storageKeys.STATE);if(!o||o!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const o=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o})}catch(o){this.logger.warn("Token revocation failed:",o)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);const t={status:"unauthenticated",user:null,accessToken:null,error:null};return this.setAuthState(t),t}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const o=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:this.redirectUri,client_id:this.authClientId,code_verifier:t})});if(!o.ok){const a=await o.text();throw new Error(`Token exchange failed: ${o.status} ${a}`)}const s=await o.json();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){const a=Date.now()+s.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,a.toString())}}async _storageGet(e){return localStorage.getItem(e)}async _storageSet(e){Object.entries(e).forEach(([t,o])=>{localStorage.setItem(t,String(o))})}async _storageRemove(e){e.forEach(t=>localStorage.removeItem(t))}_getRedirectUri(){return this.redirectUri}}const g=500,E=5e3;class S{constructor(e,t,o){this.state=r.EXTENSION_STATE_NOT_INITIALIZED,this.bodhiext=null,this.refreshPromise=null,this.logger=new r.Logger("WindowBodhiextClient",t.logLevel),this.authClientId=e,this.config=t,this.authEndpoints=r.createOAuthEndpoints(this.config.authServerUrl),this.onStateChange=o??r.NOOP_STATE_CALLBACK;const s=r.createStoragePrefixWithBasePath(t.basePath,r.STORAGE_PREFIXES.WEB_EXT);this.storageKeys=r.createStorageKeys(s)}setState(e){this.state=e,this.logger.info(`{state: ${JSON.stringify(e)}} - Setting client state`),this.onStateChange({type:"client-state",state:e})}setAuthState(e){this.onStateChange({type:"auth-state",state:e})}setStateCallback(e){this.onStateChange=e}ensureBodhiext(){if(!this.bodhiext&&window.bodhiext&&(this.logger.info("Acquiring window.bodhiext reference"),this.bodhiext=window.bodhiext),!this.bodhiext)throw r.createOperationError("Client not initialized","extension_error")}async sendExtRequest(e,t){return this.ensureBodhiext(),this.bodhiext.sendExtRequest(e,t)}async sendApiRequest(e,t,o,s,a){try{this.ensureBodhiext()}catch(i){return{error:{message:i instanceof Error?i.message:String(i),type:"extension_error"}}}try{let i=s||{};if(a){const c=await this._getAccessTokenRaw();if(!c)return{error:{message:"Not authenticated. Please log in first.",type:"extension_error"}};i={...i,Authorization:`Bearer ${c}`}}return await this.bodhiext.sendApiRequest(e,t,o,i)}catch(i){const h=i?.error,c=h?.message??(i instanceof Error?i.message:String(i)),n=h?.type||"extension_error";return{error:{message:c,type:n}}}}getState(){return this.state}isClientInitialized(){return this.state.extension==="ready"}isServerReady(){return this.isClientInitialized()&&this.state.server.status==="ready"}async init(e={}){if(!e.testConnection&&!e.selectedConnection)return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"),r.EXTENSION_STATE_NOT_INITIALIZED;if(this.bodhiext&&!e.testConnection)return this.logger.debug("Already have bodhiext handle, skipping polling"),this.state;if(!this.bodhiext){const s=e.timeoutMs??this.config.initParams?.extension?.timeoutMs??E,a=e.intervalMs??this.config.initParams?.extension?.intervalMs??g,i=Date.now();if(!await new Promise(c=>{const n=()=>{if(window.bodhiext){this.bodhiext=window.bodhiext,c(!0);return}if(Date.now()-i>=s){c(!1);return}setTimeout(n,a)};n()}))return this.logger.warn("Extension discovery timed out"),this.setState(r.EXTENSION_STATE_NOT_FOUND),this.state}const t=await this.bodhiext.getExtensionId();this.logger.info(`Extension discovered: ${t}`);const o={type:"extension",extension:"ready",extensionId:t,server:r.PENDING_EXTENSION_READY};if(e.testConnection)try{const s=await this.getServerState();this.setState({...o,server:s}),this.logger.info(`Server connectivity tested: ${s.status}`)}catch(s){this.logger.error("Failed to get server state:",s),this.setState({...o,server:r.BACKEND_SERVER_NOT_REACHABLE})}else this.setState(o);return this.state}async requestResourceAccess(){return this.ensureBodhiext(),this.bodhiext.sendApiRequest("POST","/bodhi/v1/apps/request-access",{app_client_id:this.authClientId})}async login(){const e=await this.getAuthState();if(e.status==="authenticated")return e;this.ensureBodhiext();const t=await this.requestResourceAccess();if(r.isApiResultOperationError(t))throw r.createOperationError(t.error.message,t.error.type);if(r.isApiResultError(t)){const{message:l}=t.body.error;throw r.createOperationError(l,"auth_error")}if(!r.isApiResultSuccess(t))throw r.createOperationError(`Unexpected HTTP ${t.status}`,"auth_error");const o=t.body.scope;localStorage.setItem(this.storageKeys.RESOURCE_SCOPE,o);const s=r.generateCodeVerifier(),a=await r.generateCodeChallenge(s),i=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,s),localStorage.setItem(this.storageKeys.STATE,i);const h=["openid","profile","email","roles",this.config.userScope,o],c=new URLSearchParams({response_type:"code",client_id:this.authClientId,redirect_uri:this.config.redirectUri,scope:h.join(" "),state:i,code_challenge:a,code_challenge_method:"S256"}),n=`${this.authEndpoints.authorize}?${c}`;return window.location.href=n,new Promise(()=>{})}async handleOAuthCallback(e,t){const o=localStorage.getItem(this.storageKeys.STATE);if(!o||o!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const o=new URLSearchParams({grant_type:"authorization_code",client_id:this.authClientId,code:e,redirect_uri:this.config.redirectUri,code_verifier:t}),s=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o});if(!s.ok){const i=await s.text();throw new Error(`Token exchange failed: ${s.status} ${i}`)}const a=await s.json();if(!a.access_token)throw new Error("No access token received");if(localStorage.setItem(this.storageKeys.ACCESS_TOKEN,a.access_token),a.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,a.refresh_token),a.expires_in){const i=Date.now()+a.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,i.toString())}}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const o=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o})}catch(o){this.logger.warn("Token revocation failed:",o)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE),localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);const t={status:"unauthenticated",user:null,accessToken:null,error:null};return this.setAuthState(t),t}async getAuthState(){const e=await this._getAccessTokenRaw();if(!e)return{status:"unauthenticated",user:null,accessToken:null,error:null};try{return{status:"authenticated",user:r.extractUserInfo(e),accessToken:e,error:null}}catch(t){return this.logger.error("Failed to parse token:",t),{status:"unauthenticated",user:null,accessToken:null,error:null}}}async _getAccessTokenRaw(){const e=localStorage.getItem(this.storageKeys.ACCESS_TOKEN),t=localStorage.getItem(this.storageKeys.EXPIRES_AT);if(!e)return null;if(t){const o=parseInt(t,10);if(Date.now()>=o-5*1e3){const s=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);return s?this._tryRefreshToken(s):null}}return e}async _tryRefreshToken(e){if(this.refreshPromise)return this.logger.debug("Refresh already in progress, returning existing promise"),this.refreshPromise;this.refreshPromise=this._doRefreshToken(e);try{return await this.refreshPromise}finally{this.refreshPromise=null}}async _doRefreshToken(e){this.logger.debug("Refreshing access token");try{const t=await r.refreshAccessToken(this.authEndpoints.token,e,this.authClientId);if(t){this._storeRefreshedTokens(t);const o=r.extractUserInfo(t.access_token);return this.setAuthState({status:"authenticated",user:o,accessToken:t.access_token,error:null}),this.logger.info("Token refreshed successfully"),t.access_token}}catch(t){this.logger.warn("Token refresh failed:",t)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),r.createOperationError("Access token expired and unable to refresh. Try logging out and logging in again.","token_refresh_failed")}_storeRefreshedTokens(e){const t=Date.now()+e.expires_in*1e3;localStorage.setItem(this.storageKeys.ACCESS_TOKEN,e.access_token),localStorage.setItem(this.storageKeys.EXPIRES_AT,String(t)),e.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,e.refresh_token)}async pingApi(){return this.sendApiRequest("GET","/ping")}async getServerState(){const e=await this.sendApiRequest("GET","/bodhi/v1/info");if(r.isApiResultOperationError(e)||!r.isApiResultSuccess(e))return r.BACKEND_SERVER_NOT_REACHABLE;const t=e.body;switch(t.status){case"ready":return{status:"ready",version:t.version||"unknown",error:null};case"setup":return r.backendServerNotReady("setup",t.version||"unknown");case"resource-admin":return r.backendServerNotReady("resource-admin",t.version||"unknown");case"error":return r.backendServerNotReady("error",t.version||"unknown",t.error?{message:t.error.message,type:t.error.type}:r.SERVER_ERROR_CODES.SERVER_NOT_READY);default:return r.BACKEND_SERVER_NOT_REACHABLE}}async*stream(e,t,o,s,a=!0){this.ensureBodhiext();let i=s||{};if(a){const n=await this._getAccessTokenRaw();if(!n)throw r.createOperationError("Not authenticated. Please log in first.","auth_error");i={...i,Authorization:`Bearer ${n}`}}const c=this.bodhiext.sendStreamRequest(e,t,o,i).getReader();try{for(;;){const{value:n,done:l}=await c.read();if(l||n?.done)break;yield n.body}}catch(n){if(n instanceof Error){if("response"in n){const l=n;throw r.createApiError(n.message,l.response.status,l.response.body)}throw"error"in n,r.createOperationError(n.message,"extension_error")}throw n}finally{c.releaseLock()}}get chat(){return this._chat??=new r.Chat(this)}get models(){return this._models??=new r.Models(this)}get embeddings(){return this._embeddings??=new r.Embeddings(this)}serialize(){return{extensionId:this.state.type==="extension"&&this.state.extension==="ready"?this.state.extensionId:void 0}}async debug(){return{type:"WindowBodhiextClient",state:this.state,authState:await this.getAuthState(),bodhiextAvailable:this.bodhiext!==null,authClientId:this.authClientId,authServerUrl:this.config.authServerUrl,redirectUri:this.config.redirectUri,userScope:this.config.userScope}}}function f(u){if(typeof window>"u")throw new Error("redirectUri required in non-browser environment");const e=u==="/"?"":u.replace(/\/$/,"");return`${window.location.origin}${e}/callback`}class _ extends r.BaseFacadeClient{constructor(e,t,o){const s=t||{},a={basePath:s.basePath||"/",redirectUri:s.redirectUri||f(s.basePath||"/"),authServerUrl:s.authServerUrl||"https://id.getbodhi.app/realms/bodhi",userScope:s.userScope||"scope_user_user",logLevel:s.logLevel||"warn",initParams:s.initParams};super(e,a,o)}createLogger(e){return new r.Logger("WebUIClient",e.logLevel)}createStoragePrefix(e){return r.createStoragePrefixWithBasePath(e.basePath,r.STORAGE_PREFIXES.WEB)}createExtClient(e,t){return new S(this.authClientId,{authServerUrl:e.authServerUrl,redirectUri:e.redirectUri,userScope:e.userScope,basePath:e.basePath,logLevel:e.logLevel,initParams:e.initParams},t)}createDirectClient(e,t,o){return new d({authClientId:e,authServerUrl:t.authServerUrl,redirectUri:t.redirectUri,userScope:t.userScope,logLevel:t.logLevel,basePath:t.basePath},o)}async handleOAuthCallback(e,t){return this.connectionMode==="direct"?this.directClient.handleOAuthCallback(e,t):this.extClient.handleOAuthCallback(e,t)}}const p="production";exports.WEB_BUILD_MODE=p;exports.WebUIClient=_;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("@bodhiapp/bodhi-js-core");class d extends r.DirectClientBase{constructor(e,t){const o=r.createStoragePrefixWithBasePath(e.basePath,r.STORAGE_PREFIXES.WEB_DIRECT),s={authClientId:e.authClientId,authServerUrl:e.authServerUrl,userScope:e.userScope,storagePrefix:o,logLevel:e.logLevel,loggerPrefix:"DirectWebClient"};super(s,t),this.redirectUri=e.redirectUri}async login(){const e=await this.getAuthState();if(e.status==="authenticated")return e;const t=await this.requestResourceAccess();if(r.isApiResultOperationError(t))throw r.createOperationError(t.error.message,t.error.type);if(r.isApiResultError(t)){const{message:n}=t.body.error;throw r.createOperationError(n,"auth_error")}if(!r.isApiResultSuccess(t))throw r.createOperationError(`Unexpected HTTP ${t.status}`,"auth_error");const o=t.body.scope;localStorage.setItem(this.storageKeys.RESOURCE_SCOPE,o);const s=`openid profile email roles ${this.userScope} ${o}`,i=r.generateCodeVerifier(),a=await r.generateCodeChallenge(i),h=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,i),localStorage.setItem(this.storageKeys.STATE,h);const c=new URL(this.authEndpoints.authorize);throw c.searchParams.set("client_id",this.authClientId),c.searchParams.set("response_type","code"),c.searchParams.set("redirect_uri",this.redirectUri),c.searchParams.set("scope",s),c.searchParams.set("code_challenge",a),c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("state",h),window.location.href=c.toString(),new Error("Redirect initiated")}async handleOAuthCallback(e,t){const o=localStorage.getItem(this.storageKeys.STATE);if(!o||o!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const o=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o})}catch(o){this.logger.warn("Token revocation failed:",o)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);const t={status:"unauthenticated",user:null,accessToken:null,error:null};return this.setAuthState(t),t}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const o=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:this.redirectUri,client_id:this.authClientId,code_verifier:t})});if(!o.ok){const i=await o.text();throw new Error(`Token exchange failed: ${o.status} ${i}`)}const s=await o.json();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){const i=Date.now()+s.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,i.toString())}}async _storageGet(e){return localStorage.getItem(e)}async _storageSet(e){Object.entries(e).forEach(([t,o])=>{localStorage.setItem(t,String(o))})}async _storageRemove(e){e.forEach(t=>localStorage.removeItem(t))}_getRedirectUri(){return this.redirectUri}}const g=500,S=5e3;class E{constructor(e,t,o){this.state=r.EXTENSION_STATE_NOT_INITIALIZED,this.bodhiext=null,this.refreshPromise=null,this.logger=new r.Logger("WindowBodhiextClient",t.logLevel),this.authClientId=e,this.config=t,this.authEndpoints=r.createOAuthEndpoints(this.config.authServerUrl),this.onStateChange=o??r.NOOP_STATE_CALLBACK;const s=r.createStoragePrefixWithBasePath(t.basePath,r.STORAGE_PREFIXES.WEB_EXT);this.storageKeys=r.createStorageKeys(s)}setState(e){this.state=e,this.logger.info(`{state: ${JSON.stringify(e)}} - Setting client state`),this.onStateChange({type:"client-state",state:e})}setAuthState(e){this.onStateChange({type:"auth-state",state:e})}setStateCallback(e){this.onStateChange=e}ensureBodhiext(){if(!this.bodhiext&&window.bodhiext&&(this.logger.info("Acquiring window.bodhiext reference"),this.bodhiext=window.bodhiext),!this.bodhiext)throw r.createOperationError("Client not initialized","extension_error")}async sendExtRequest(e,t){return this.ensureBodhiext(),this.bodhiext.sendExtRequest(e,t)}async sendApiRequest(e,t,o,s,i){try{this.ensureBodhiext()}catch(a){return{error:{message:a instanceof Error?a.message:String(a),type:"extension_error"}}}try{let a=s||{};if(i){const c=await this._getAccessTokenRaw();if(!c)return{error:{message:"Not authenticated. Please log in first.",type:"extension_error"}};a={...a,Authorization:`Bearer ${c}`}}return await this.bodhiext.sendApiRequest(e,t,o,a)}catch(a){const h=a?.error,c=h?.message??(a instanceof Error?a.message:String(a)),n=h?.type||"extension_error";return{error:{message:c,type:n}}}}getState(){return this.state}isClientInitialized(){return this.state.extension==="ready"}isServerReady(){return this.isClientInitialized()&&this.state.server.status==="ready"}async init(e={}){if(!e.testConnection&&!e.selectedConnection)return this.logger.info("No testConnection or selectedConnection, returning not-initialized state"),r.EXTENSION_STATE_NOT_INITIALIZED;if(this.bodhiext&&!e.testConnection)return this.logger.debug("Already have bodhiext handle, skipping polling"),this.state;if(!this.bodhiext){const s=e.timeoutMs??this.config.initParams?.extension?.timeoutMs??S,i=e.intervalMs??this.config.initParams?.extension?.intervalMs??g,a=Date.now();if(!await new Promise(c=>{const n=()=>{if(window.bodhiext){this.bodhiext=window.bodhiext,c(!0);return}if(Date.now()-a>=s){c(!1);return}setTimeout(n,i)};n()}))return this.logger.warn("Extension discovery timed out"),this.setState(r.EXTENSION_STATE_NOT_FOUND),this.state}const t=await this.bodhiext.getExtensionId();this.logger.info(`Extension discovered: ${t}`);const o={type:"extension",extension:"ready",extensionId:t,server:r.PENDING_EXTENSION_READY};if(e.testConnection)try{const s=await this.getServerState();this.setState({...o,server:s}),this.logger.info(`Server connectivity tested: ${s.status}`)}catch(s){this.logger.error("Failed to get server state:",s),this.setState({...o,server:r.BACKEND_SERVER_NOT_REACHABLE})}else this.setState(o);return this.state}async requestResourceAccess(){return this.ensureBodhiext(),this.bodhiext.sendApiRequest("POST","/bodhi/v1/apps/request-access",{app_client_id:this.authClientId})}async login(){const e=await this.getAuthState();if(e.status==="authenticated")return e;this.ensureBodhiext();const t=await this.requestResourceAccess();if(r.isApiResultOperationError(t))throw r.createOperationError(t.error.message,t.error.type);if(r.isApiResultError(t)){const{message:l}=t.body.error;throw r.createOperationError(l,"auth_error")}if(!r.isApiResultSuccess(t))throw r.createOperationError(`Unexpected HTTP ${t.status}`,"auth_error");const o=t.body.scope;localStorage.setItem(this.storageKeys.RESOURCE_SCOPE,o);const s=r.generateCodeVerifier(),i=await r.generateCodeChallenge(s),a=r.generateCodeVerifier();localStorage.setItem(this.storageKeys.CODE_VERIFIER,s),localStorage.setItem(this.storageKeys.STATE,a);const h=["openid","profile","email","roles",this.config.userScope,o],c=new URLSearchParams({response_type:"code",client_id:this.authClientId,redirect_uri:this.config.redirectUri,scope:h.join(" "),state:a,code_challenge:i,code_challenge_method:"S256"}),n=`${this.authEndpoints.authorize}?${c}`;return window.location.href=n,new Promise(()=>{})}async handleOAuthCallback(e,t){const o=localStorage.getItem(this.storageKeys.STATE);if(!o||o!==t)throw new Error("Invalid state parameter - possible CSRF attack");await this.exchangeCodeForTokens(e),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE);const s=await this.getAuthState();if(s.status!=="authenticated")throw new Error("Login failed");return this.setAuthState(s),s}async exchangeCodeForTokens(e){const t=localStorage.getItem(this.storageKeys.CODE_VERIFIER);if(!t)throw new Error("Code verifier not found");const o=new URLSearchParams({grant_type:"authorization_code",client_id:this.authClientId,code:e,redirect_uri:this.config.redirectUri,code_verifier:t}),s=await fetch(this.authEndpoints.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o});if(!s.ok){const a=await s.text();throw new Error(`Token exchange failed: ${s.status} ${a}`)}const i=await s.json();if(!i.access_token)throw new Error("No access token received");if(localStorage.setItem(this.storageKeys.ACCESS_TOKEN,i.access_token),i.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,i.refresh_token),i.expires_in){const a=Date.now()+i.expires_in*1e3;localStorage.setItem(this.storageKeys.EXPIRES_AT,a.toString())}}async logout(){const e=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);if(e)try{const o=new URLSearchParams({token:e,client_id:this.authClientId,token_type_hint:"refresh_token"});await fetch(this.authEndpoints.revoke,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o})}catch(o){this.logger.warn("Token revocation failed:",o)}localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.CODE_VERIFIER),localStorage.removeItem(this.storageKeys.STATE),localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);const t={status:"unauthenticated",user:null,accessToken:null,error:null};return this.setAuthState(t),t}async getAuthState(){const e=await this._getAccessTokenRaw();if(!e)return{status:"unauthenticated",user:null,accessToken:null,error:null};try{return{status:"authenticated",user:r.extractUserInfo(e),accessToken:e,error:null}}catch(t){return this.logger.error("Failed to parse token:",t),{status:"unauthenticated",user:null,accessToken:null,error:null}}}async _getAccessTokenRaw(){const e=localStorage.getItem(this.storageKeys.ACCESS_TOKEN),t=localStorage.getItem(this.storageKeys.EXPIRES_AT);if(!e)return null;if(t){const o=parseInt(t,10);if(Date.now()>=o-5*1e3){const s=localStorage.getItem(this.storageKeys.REFRESH_TOKEN);return s?this._tryRefreshToken(s):null}}return e}async _tryRefreshToken(e){if(this.refreshPromise)return this.logger.debug("Refresh already in progress, returning existing promise"),this.refreshPromise;this.refreshPromise=this._doRefreshToken(e);try{return await this.refreshPromise}finally{this.refreshPromise=null}}async _doRefreshToken(e){this.logger.debug("Refreshing access token");try{const t=await r.refreshAccessToken(this.authEndpoints.token,e,this.authClientId);if(t.success){this._storeRefreshedTokens(t.tokens);const o=r.extractUserInfo(t.tokens.access_token);return this.setAuthState({status:"authenticated",user:o,accessToken:t.tokens.access_token,error:null}),this.logger.info("Token refreshed successfully"),t.tokens.access_token}if(t.error==="invalid_grant")return this.logger.warn("Refresh token expired or revoked, clearing tokens and logging out"),this.clearAuthStorage(),this.setAuthState({status:"unauthenticated",user:null,accessToken:null,error:null}),null}catch(t){this.logger.warn("Token refresh failed:",t)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),r.createOperationError("Access token expired and unable to refresh. Try logging out and logging in again.","token_refresh_failed")}clearAuthStorage(){localStorage.removeItem(this.storageKeys.ACCESS_TOKEN),localStorage.removeItem(this.storageKeys.REFRESH_TOKEN),localStorage.removeItem(this.storageKeys.EXPIRES_AT),localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE)}_storeRefreshedTokens(e){const t=Date.now()+e.expires_in*1e3;localStorage.setItem(this.storageKeys.ACCESS_TOKEN,e.access_token),localStorage.setItem(this.storageKeys.EXPIRES_AT,String(t)),e.refresh_token&&localStorage.setItem(this.storageKeys.REFRESH_TOKEN,e.refresh_token)}async pingApi(){return this.sendApiRequest("GET","/ping")}async getServerState(){const e=await this.sendApiRequest("GET","/bodhi/v1/info");if(r.isApiResultOperationError(e)||!r.isApiResultSuccess(e))return r.BACKEND_SERVER_NOT_REACHABLE;const t=e.body;switch(t.status){case"ready":return{status:"ready",version:t.version||"unknown",error:null};case"setup":return r.backendServerNotReady("setup",t.version||"unknown");case"resource-admin":return r.backendServerNotReady("resource-admin",t.version||"unknown");case"error":return r.backendServerNotReady("error",t.version||"unknown",t.error?{message:t.error.message,type:t.error.type}:r.SERVER_ERROR_CODES.SERVER_NOT_READY);default:return r.BACKEND_SERVER_NOT_REACHABLE}}async*stream(e,t,o,s,i=!0){this.ensureBodhiext();let a=s||{};if(i){const n=await this._getAccessTokenRaw();if(!n)throw r.createOperationError("Not authenticated. Please log in first.","auth_error");a={...a,Authorization:`Bearer ${n}`}}const c=this.bodhiext.sendStreamRequest(e,t,o,a).getReader();try{for(;;){const{value:n,done:l}=await c.read();if(l||n?.done)break;yield n.body}}catch(n){if(n instanceof Error){if("response"in n){const l=n;throw r.createApiError(n.message,l.response.status,l.response.body)}throw"error"in n,r.createOperationError(n.message,"extension_error")}throw n}finally{c.releaseLock()}}get chat(){return this._chat??=new r.Chat(this)}get models(){return this._models??=new r.Models(this)}get embeddings(){return this._embeddings??=new r.Embeddings(this)}serialize(){return{extensionId:this.state.type==="extension"&&this.state.extension==="ready"?this.state.extensionId:void 0}}async debug(){return{type:"WindowBodhiextClient",state:this.state,authState:await this.getAuthState(),bodhiextAvailable:this.bodhiext!==null,authClientId:this.authClientId,authServerUrl:this.config.authServerUrl,redirectUri:this.config.redirectUri,userScope:this.config.userScope}}}function f(u){if(typeof window>"u")throw new Error("redirectUri required in non-browser environment");const e=u==="/"?"":u.replace(/\/$/,"");return`${window.location.origin}${e}/callback`}class _ extends r.BaseFacadeClient{constructor(e,t,o){const s=t||{},i={basePath:s.basePath||"/",redirectUri:s.redirectUri||f(s.basePath||"/"),authServerUrl:s.authServerUrl||"https://id.getbodhi.app/realms/bodhi",userScope:s.userScope||"scope_user_user",logLevel:s.logLevel||"warn",initParams:s.initParams};super(e,i,o)}createLogger(e){return new r.Logger("WebUIClient",e.logLevel)}createStoragePrefix(e){return r.createStoragePrefixWithBasePath(e.basePath,r.STORAGE_PREFIXES.WEB)}createExtClient(e,t){return new E(this.authClientId,{authServerUrl:e.authServerUrl,redirectUri:e.redirectUri,userScope:e.userScope,basePath:e.basePath,logLevel:e.logLevel,initParams:e.initParams},t)}createDirectClient(e,t,o){return new d({authClientId:e,authServerUrl:t.authServerUrl,redirectUri:t.redirectUri,userScope:t.userScope,logLevel:t.logLevel,basePath:t.basePath},o)}async handleOAuthCallback(e,t){return this.connectionMode==="direct"?this.directClient.handleOAuthCallback(e,t):this.extClient.handleOAuthCallback(e,t)}}const p="production";exports.WEB_BUILD_MODE=p;exports.WebUIClient=_;
@@ -1,4 +1,4 @@
1
- import { DirectClientBase as R, createStoragePrefixWithBasePath as m, STORAGE_PREFIXES as _, isApiResultOperationError as E, createOperationError as h, isApiResultError as y, isApiResultSuccess as f, generateCodeVerifier as g, generateCodeChallenge as T, EXTENSION_STATE_NOT_INITIALIZED as w, Logger as I, createOAuthEndpoints as C, NOOP_STATE_CALLBACK as x, createStorageKeys as k, EXTENSION_STATE_NOT_FOUND as A, PENDING_EXTENSION_READY as v, BACKEND_SERVER_NOT_REACHABLE as d, extractUserInfo as p, refreshAccessToken as b, backendServerNotReady as S, SERVER_ERROR_CODES as P, createApiError as O, Chat as K, Models as U, Embeddings as N, BaseFacadeClient as L } from "@bodhiapp/bodhi-js-core";
1
+ import { DirectClientBase as R, createStoragePrefixWithBasePath as m, STORAGE_PREFIXES as _, isApiResultOperationError as E, createOperationError as h, isApiResultError as p, isApiResultSuccess as f, generateCodeVerifier as g, generateCodeChallenge as T, EXTENSION_STATE_NOT_INITIALIZED as w, Logger as I, createOAuthEndpoints as C, NOOP_STATE_CALLBACK as k, createStorageKeys as x, EXTENSION_STATE_NOT_FOUND as A, PENDING_EXTENSION_READY as v, BACKEND_SERVER_NOT_REACHABLE as d, extractUserInfo as y, refreshAccessToken as b, backendServerNotReady as S, SERVER_ERROR_CODES as O, createApiError as P, Chat as K, Models as U, Embeddings as N, BaseFacadeClient as L } from "@bodhiapp/bodhi-js-core";
2
2
  class D extends R {
3
3
  constructor(e, t) {
4
4
  const s = m(
@@ -24,16 +24,16 @@ class D extends R {
24
24
  const t = await this.requestResourceAccess();
25
25
  if (E(t))
26
26
  throw h(t.error.message, t.error.type);
27
- if (y(t)) {
28
- const { message: a } = t.body.error;
29
- throw h(a, "auth_error");
27
+ if (p(t)) {
28
+ const { message: i } = t.body.error;
29
+ throw h(i, "auth_error");
30
30
  }
31
31
  if (!f(t))
32
32
  throw h(`Unexpected HTTP ${t.status}`, "auth_error");
33
33
  const s = t.body.scope;
34
34
  localStorage.setItem(this.storageKeys.RESOURCE_SCOPE, s);
35
- const r = `openid profile email roles ${this.userScope} ${s}`, i = g(), o = await T(i), c = g();
36
- localStorage.setItem(this.storageKeys.CODE_VERIFIER, i), localStorage.setItem(this.storageKeys.STATE, c);
35
+ const r = `openid profile email roles ${this.userScope} ${s}`, a = g(), o = await T(a), c = g();
36
+ localStorage.setItem(this.storageKeys.CODE_VERIFIER, a), localStorage.setItem(this.storageKeys.STATE, c);
37
37
  const n = new URL(this.authEndpoints.authorize);
38
38
  throw n.searchParams.set("client_id", this.authClientId), n.searchParams.set("response_type", "code"), n.searchParams.set("redirect_uri", this.redirectUri), n.searchParams.set("scope", r), n.searchParams.set("code_challenge", o), n.searchParams.set("code_challenge_method", "S256"), n.searchParams.set("state", c), window.location.href = n.toString(), new Error("Redirect initiated");
39
39
  }
@@ -96,13 +96,13 @@ class D extends R {
96
96
  })
97
97
  });
98
98
  if (!s.ok) {
99
- const i = await s.text();
100
- throw new Error(`Token exchange failed: ${s.status} ${i}`);
99
+ const a = await s.text();
100
+ throw new Error(`Token exchange failed: ${s.status} ${a}`);
101
101
  }
102
102
  const r = await s.json();
103
103
  if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, r.access_token), r.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, r.refresh_token), r.expires_in) {
104
- const i = Date.now() + r.expires_in * 1e3;
105
- localStorage.setItem(this.storageKeys.EXPIRES_AT, i.toString());
104
+ const a = Date.now() + r.expires_in * 1e3;
105
+ localStorage.setItem(this.storageKeys.EXPIRES_AT, a.toString());
106
106
  }
107
107
  }
108
108
  // ============================================================================
@@ -126,9 +126,9 @@ class D extends R {
126
126
  const F = 500, B = 5e3;
127
127
  class $ {
128
128
  constructor(e, t, s) {
129
- this.state = w, this.bodhiext = null, this.refreshPromise = null, this.logger = new I("WindowBodhiextClient", t.logLevel), this.authClientId = e, this.config = t, this.authEndpoints = C(this.config.authServerUrl), this.onStateChange = s ?? x;
129
+ this.state = w, this.bodhiext = null, this.refreshPromise = null, this.logger = new I("WindowBodhiextClient", t.logLevel), this.authClientId = e, this.config = t, this.authEndpoints = C(this.config.authServerUrl), this.onStateChange = s ?? k;
130
130
  const r = m(t.basePath, _.WEB_EXT);
131
- this.storageKeys = k(r);
131
+ this.storageKeys = x(r);
132
132
  }
133
133
  /**
134
134
  * Set client state and notify callback
@@ -169,7 +169,7 @@ class $ {
169
169
  * Send API message via window.bodhiext.sendApiRequest
170
170
  * Converts ApiResponse to ApiResponseResult
171
171
  */
172
- async sendApiRequest(e, t, s, r, i) {
172
+ async sendApiRequest(e, t, s, r, a) {
173
173
  try {
174
174
  this.ensureBodhiext();
175
175
  } catch (o) {
@@ -182,7 +182,7 @@ class $ {
182
182
  }
183
183
  try {
184
184
  let o = r || {};
185
- if (i) {
185
+ if (a) {
186
186
  const n = await this._getAccessTokenRaw();
187
187
  if (!n)
188
188
  return {
@@ -203,11 +203,11 @@ class $ {
203
203
  o
204
204
  );
205
205
  } catch (o) {
206
- const c = o?.error, n = c?.message ?? (o instanceof Error ? o.message : String(o)), a = c?.type || "extension_error";
206
+ const c = o?.error, n = c?.message ?? (o instanceof Error ? o.message : String(o)), i = c?.type || "extension_error";
207
207
  return {
208
208
  error: {
209
209
  message: n,
210
- type: a
210
+ type: i
211
211
  }
212
212
  };
213
213
  }
@@ -237,9 +237,9 @@ class $ {
237
237
  if (this.bodhiext && !e.testConnection)
238
238
  return this.logger.debug("Already have bodhiext handle, skipping polling"), this.state;
239
239
  if (!this.bodhiext) {
240
- const r = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? B, i = e.intervalMs ?? this.config.initParams?.extension?.intervalMs ?? F, o = Date.now();
240
+ const r = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? B, a = e.intervalMs ?? this.config.initParams?.extension?.intervalMs ?? F, o = Date.now();
241
241
  if (!await new Promise((n) => {
242
- const a = () => {
242
+ const i = () => {
243
243
  if (window.bodhiext) {
244
244
  this.bodhiext = window.bodhiext, n(!0);
245
245
  return;
@@ -248,9 +248,9 @@ class $ {
248
248
  n(!1);
249
249
  return;
250
250
  }
251
- setTimeout(a, i);
251
+ setTimeout(i, a);
252
252
  };
253
- a();
253
+ i();
254
254
  }))
255
255
  return this.logger.warn("Extension discovery timed out"), this.setState(A), this.state;
256
256
  }
@@ -299,7 +299,7 @@ class $ {
299
299
  const t = await this.requestResourceAccess();
300
300
  if (E(t))
301
301
  throw h(t.error.message, t.error.type);
302
- if (y(t)) {
302
+ if (p(t)) {
303
303
  const { message: l } = t.body.error;
304
304
  throw h(l, "auth_error");
305
305
  }
@@ -307,7 +307,7 @@ class $ {
307
307
  throw h(`Unexpected HTTP ${t.status}`, "auth_error");
308
308
  const s = t.body.scope;
309
309
  localStorage.setItem(this.storageKeys.RESOURCE_SCOPE, s);
310
- const r = g(), i = await T(r), o = g();
310
+ const r = g(), a = await T(r), o = g();
311
311
  localStorage.setItem(this.storageKeys.CODE_VERIFIER, r), localStorage.setItem(this.storageKeys.STATE, o);
312
312
  const c = ["openid", "profile", "email", "roles", this.config.userScope, s], n = new URLSearchParams({
313
313
  response_type: "code",
@@ -315,10 +315,10 @@ class $ {
315
315
  redirect_uri: this.config.redirectUri,
316
316
  scope: c.join(" "),
317
317
  state: o,
318
- code_challenge: i,
318
+ code_challenge: a,
319
319
  code_challenge_method: "S256"
320
- }), a = `${this.authEndpoints.authorize}?${n}`;
321
- return window.location.href = a, new Promise(() => {
320
+ }), i = `${this.authEndpoints.authorize}?${n}`;
321
+ return window.location.href = i, new Promise(() => {
322
322
  });
323
323
  }
324
324
  /**
@@ -360,11 +360,11 @@ class $ {
360
360
  const o = await r.text();
361
361
  throw new Error(`Token exchange failed: ${r.status} ${o}`);
362
362
  }
363
- const i = await r.json();
364
- if (!i.access_token)
363
+ const a = await r.json();
364
+ if (!a.access_token)
365
365
  throw new Error("No access token received");
366
- if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, i.access_token), i.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, i.refresh_token), i.expires_in) {
367
- const o = Date.now() + i.expires_in * 1e3;
366
+ if (localStorage.setItem(this.storageKeys.ACCESS_TOKEN, a.access_token), a.refresh_token && localStorage.setItem(this.storageKeys.REFRESH_TOKEN, a.refresh_token), a.expires_in) {
367
+ const o = Date.now() + a.expires_in * 1e3;
368
368
  localStorage.setItem(this.storageKeys.EXPIRES_AT, o.toString());
369
369
  }
370
370
  }
@@ -408,7 +408,7 @@ class $ {
408
408
  if (!e)
409
409
  return { status: "unauthenticated", user: null, accessToken: null, error: null };
410
410
  try {
411
- return { status: "authenticated", user: p(e), accessToken: e, error: null };
411
+ return { status: "authenticated", user: y(e), accessToken: e, error: null };
412
412
  } catch (t) {
413
413
  return this.logger.error("Failed to parse token:", t), { status: "unauthenticated", user: null, accessToken: null, error: null };
414
414
  }
@@ -455,16 +455,23 @@ class $ {
455
455
  e,
456
456
  this.authClientId
457
457
  );
458
- if (t) {
459
- this._storeRefreshedTokens(t);
460
- const s = p(t.access_token);
458
+ if (t.success) {
459
+ this._storeRefreshedTokens(t.tokens);
460
+ const s = y(t.tokens.access_token);
461
461
  return this.setAuthState({
462
462
  status: "authenticated",
463
463
  user: s,
464
- accessToken: t.access_token,
464
+ accessToken: t.tokens.access_token,
465
465
  error: null
466
- }), this.logger.info("Token refreshed successfully"), t.access_token;
466
+ }), this.logger.info("Token refreshed successfully"), t.tokens.access_token;
467
467
  }
468
+ if (t.error === "invalid_grant")
469
+ return this.logger.warn("Refresh token expired or revoked, clearing tokens and logging out"), this.clearAuthStorage(), this.setAuthState({
470
+ status: "unauthenticated",
471
+ user: null,
472
+ accessToken: null,
473
+ error: null
474
+ }), null;
468
475
  } catch (t) {
469
476
  this.logger.warn("Token refresh failed:", t);
470
477
  }
@@ -473,6 +480,9 @@ class $ {
473
480
  "token_refresh_failed"
474
481
  );
475
482
  }
483
+ clearAuthStorage() {
484
+ localStorage.removeItem(this.storageKeys.ACCESS_TOKEN), localStorage.removeItem(this.storageKeys.REFRESH_TOKEN), localStorage.removeItem(this.storageKeys.EXPIRES_AT), localStorage.removeItem(this.storageKeys.RESOURCE_SCOPE);
485
+ }
476
486
  /**
477
487
  * Store refreshed tokens
478
488
  */
@@ -508,7 +518,7 @@ class $ {
508
518
  return S(
509
519
  "error",
510
520
  t.version || "unknown",
511
- t.error ? { message: t.error.message, type: t.error.type } : P.SERVER_NOT_READY
521
+ t.error ? { message: t.error.message, type: t.error.type } : O.SERVER_NOT_READY
512
522
  );
513
523
  default:
514
524
  return d;
@@ -518,35 +528,35 @@ class $ {
518
528
  * Generic streaming via window.bodhiext.sendStreamRequest
519
529
  * Wraps ReadableStream as AsyncGenerator
520
530
  */
521
- async *stream(e, t, s, r, i = !0) {
531
+ async *stream(e, t, s, r, a = !0) {
522
532
  this.ensureBodhiext();
523
533
  let o = r || {};
524
- if (i) {
525
- const a = await this._getAccessTokenRaw();
526
- if (!a)
534
+ if (a) {
535
+ const i = await this._getAccessTokenRaw();
536
+ if (!i)
527
537
  throw h("Not authenticated. Please log in first.", "auth_error");
528
538
  o = {
529
539
  ...o,
530
- Authorization: `Bearer ${a}`
540
+ Authorization: `Bearer ${i}`
531
541
  };
532
542
  }
533
543
  const n = this.bodhiext.sendStreamRequest(e, t, s, o).getReader();
534
544
  try {
535
545
  for (; ; ) {
536
- const { value: a, done: l } = await n.read();
537
- if (l || a?.done)
546
+ const { value: i, done: l } = await n.read();
547
+ if (l || i?.done)
538
548
  break;
539
- yield a.body;
549
+ yield i.body;
540
550
  }
541
- } catch (a) {
542
- if (a instanceof Error) {
543
- if ("response" in a) {
544
- const l = a;
545
- throw O(a.message, l.response.status, l.response.body);
551
+ } catch (i) {
552
+ if (i instanceof Error) {
553
+ if ("response" in i) {
554
+ const l = i;
555
+ throw P(i.message, l.response.status, l.response.body);
546
556
  }
547
- throw "error" in a ? h(a.message, "extension_error") : h(a.message, "extension_error");
557
+ throw "error" in i ? h(i.message, "extension_error") : h(i.message, "extension_error");
548
558
  }
549
- throw a;
559
+ throw i;
550
560
  } finally {
551
561
  n.releaseLock();
552
562
  }
@@ -593,9 +603,9 @@ function q(u) {
593
603
  const e = u === "/" ? "" : u.replace(/\/$/, "");
594
604
  return `${window.location.origin}${e}/callback`;
595
605
  }
596
- class z extends L {
606
+ class H extends L {
597
607
  constructor(e, t, s) {
598
- const r = t || {}, i = {
608
+ const r = t || {}, a = {
599
609
  basePath: r.basePath || "/",
600
610
  redirectUri: r.redirectUri || q(r.basePath || "/"),
601
611
  authServerUrl: r.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
@@ -603,7 +613,7 @@ class z extends L {
603
613
  logLevel: r.logLevel || "warn",
604
614
  initParams: r.initParams
605
615
  };
606
- super(e, i, s);
616
+ super(e, a, s);
607
617
  }
608
618
  createLogger(e) {
609
619
  return new I("WebUIClient", e.logLevel);
@@ -645,8 +655,8 @@ class z extends L {
645
655
  return this.connectionMode === "direct" ? this.directClient.handleOAuthCallback(e, t) : this.extClient.handleOAuthCallback(e, t);
646
656
  }
647
657
  }
648
- const H = "production";
658
+ const z = "production";
649
659
  export {
650
- H as WEB_BUILD_MODE,
651
- z as WebUIClient
660
+ z as WEB_BUILD_MODE,
661
+ H as WebUIClient
652
662
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bodhiapp/bodhi-js",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "description": "Web SDK for Bodhi Browser - window.bodhiext communication",
5
5
  "type": "module",
6
6
  "main": "dist/bodhi-web.cjs.js",
@@ -37,7 +37,7 @@
37
37
  "typecheck": "tsc --noEmit"
38
38
  },
39
39
  "dependencies": {
40
- "@bodhiapp/bodhi-js-core": "0.0.10",
40
+ "@bodhiapp/bodhi-js-core": "0.0.12",
41
41
  "@bodhiapp/ts-client": "0.1.9"
42
42
  },
43
43
  "devDependencies": {