@bodhiapp/bodhi-js-core 0.0.3 → 0.0.4
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-core.cjs.js +5 -5
- package/dist/bodhi-core.esm.js +111 -100
- package/dist/bodhi-js-sdk/core/src/build-info.d.ts +1 -0
- package/dist/bodhi-js-sdk/core/src/facade-client-base.d.ts +1 -1
- package/dist/bodhi-js-sdk/core/src/index.d.ts +1 -0
- package/dist/bodhi-js-sdk/core/src/storage.d.ts +12 -0
- package/package.json +1 -1
package/dist/bodhi-core.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const z=require("ua-parser-js");function w(t){return t!==null&&typeof t=="object"}function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const z=require("ua-parser-js");function w(t){return t!==null&&typeof t=="object"}function Z(t){return w(t)&&"error"in t&&w(t.error)&&"message"in t.error&&typeof t.error.message=="string"&&"type"in t.error&&typeof t.error.type=="string"}function K(t){return w(t)&&"message"in t&&typeof t.message=="string"&&"type"in t&&typeof t.type=="string"}function J(t){return t instanceof Error&&"error"in t&&!("response"in t)&&K(t.error)}function R(t){return t!==null&&typeof t=="object"&&"error"in t&&!("body"in t)&&K(t.error)}function O(t){return"body"in t&&"status"in t&&typeof t.status=="number"&&t.status>=200&&t.status<300}function ee(t){return"body"in t&&"status"in t&&typeof t.status=="number"&&t.status>=400&&Z(t.body)}const te=(t,e,n,r)=>{const a=new Error(t);return a.response={status:e,body:n,headers:r},a},g=(t,e)=>{const n=new Error(t);return n.error={message:t,type:e},n},h={NOT_REACHABLE:{message:"server is not reachable on given url",type:"network_error"},SERVER_NOT_READY:{message:"server is not in ready state, configure to complete setup",type:"extension_error"}},y={status:"not-reachable",error:h.NOT_REACHABLE},k={status:"pending-extension-ready"},E={status:"not-connected"};function C(t){return t.status==="ready"}function L(t,e="unknown",n=h.SERVER_NOT_READY){return{status:t,version:e,error:n}}function b(t){return t.type==="extension"}function N(t){return t.type==="direct"}function ne(t){return typeof t.server=="object"&&t.server.status!=="not-connected"&&C(t.server)}function P(t){return"url"in t&&!!t.url}const v={type:"direct",server:E};function re(t,e="unknown"){return{type:"direct",server:{status:"ready",version:e},url:t}}function ae(t){return{type:"direct",server:y,url:t}}function ie(t,e){return{type:"direct",server:e,url:t}}const M={type:"extension",extension:"not-initialized",server:k},D={type:"extension",extension:"not-found",server:k};function se(t){return t.extension==="ready"&&t.server.status!=="pending-extension-ready"&&C(t.server)}function U(t){return t.extension==="ready"&&"extensionId"in t}function oe(){return M}function le(){return D}function ce(t){return b(t)?U(t):P(t)}function ue(t){return t.server}function de(t){return b(t)&&t.extension==="ready"?t.extensionId:void 0}function fe(t){return N(t)&&"url"in t?t.url:void 0}const pe={isLoggedIn:!1,error:{message:"Client not initialized",code:"CLIENT_NOT_INITIALIZED"}};function he(t){return typeof t=="object"&&t!==null&&"isLoggedIn"in t&&t.isLoggedIn===!1&&"error"in t&&typeof t.error=="object"&&t.error!==null&&"message"in t.error&&typeof t.error.message=="string"&&"code"in t.error&&typeof t.error.code=="string"}function me(t){return typeof t=="object"&&t!==null&&"isLoggedIn"in t&&t.isLoggedIn===!1&&!("error"in t)}function ge(t){return typeof t=="object"&&t!==null&&"isLoggedIn"in t&&t.isLoggedIn===!0&&"userInfo"in t&&typeof t.userInfo=="object"&&t.userInfo!==null&&"sub"in t.userInfo&&typeof t.userInfo.sub=="string"&&"accessToken"in t&&typeof t.accessToken=="string"}const _=()=>{};function B(t,e){return{kind:"event",type:t,payload:e}}function j(t,e,n){return{kind:"response",type:e,requestId:t,payload:n}}function F(t,e){return{kind:"error",requestId:t,error:e}}function ve(t,e){const n=e[t.type];if(!n)return null;const r=n(t.payload);return j(t.requestId,t.type,r)}const T={debug:0,info:1,warn:2,error:3,silent:4};class V{constructor(e,n="warn"){this.prefix=e,this.level=n}shouldLog(e){return T[e]>=T[this.level]}ts(){const e=new Date,n=e.getHours().toString().padStart(2,"0"),r=e.getMinutes().toString().padStart(2,"0"),a=e.getSeconds().toString().padStart(2,"0"),i=e.getMilliseconds().toString().padStart(3,"0");return`${n}:${r}:${a}.${i}`}debug(...e){this.shouldLog("debug")&&console.log(`[${this.prefix}] ${this.ts()}`,...e)}info(...e){this.shouldLog("info")&&console.log(`[${this.prefix}] ${this.ts()}`,...e)}warn(...e){this.shouldLog("warn")&&console.warn(`[${this.prefix}] ${this.ts()}`,...e)}error(...e){this.shouldLog("error")&&console.error(`[${this.prefix}] ${this.ts()}`,...e)}}function ye(t){return"handleOAuthCallback"in t}function be(){var a;const e=new z.UAParser().getBrowser(),n=((a=e.name)==null?void 0:a.toLowerCase())||"",r=e.name||"Unknown Browser";if(n.includes("chrome"))return{name:"Google Chrome",type:"chrome"};if(n.includes("edge"))return{name:"Microsoft Edge",type:"edge"};if(n.includes("firefox"))return{name:"Mozilla Firefox",type:"firefox"};if(n.includes("safari"))return{name:"Safari",type:"safari"};{let i=r.replace(/\s+Browser$/i,"").replace(/\s+browser$/i,"").trim();return(!i||i.toLowerCase()==="unknown")&&(i="Unknown Browser"),{name:i,type:"unknown"}}}function xe(){var r;const n=((r=new z.UAParser().getOS().name)==null?void 0:r.toLowerCase())||"";return n.includes("mac")?{name:"macOS",type:"macos"}:n.includes("windows")?{name:"Windows",type:"windows"}:n.includes("linux")||n.includes("ubuntu")||n.includes("fedora")||n.includes("debian")?{name:"Linux",type:"linux"}:{name:"Unknown",type:"unknown"}}function Q(t){return{ACCESS_TOKEN:`${t}:access_token`,REFRESH_TOKEN:`${t}:refresh_token`,EXPIRES_AT:`${t}:expires_at`,CODE_VERIFIER:`${t}:code_verifier`,STATE:`${t}:state`,RESOURCE_SCOPE:`${t}:resource_scope`}}const we={DIRECT:"bodhi:direct",WEB:"bodhi:web",EXT:"bodhi:ext"};function H(t,e){return`${t}:${e}`}class q{constructor(e="bodhijs:"){this.storagePrefix=e,this.STORAGE_KEYS={DIRECT_STATUS:`${e}connection:directStatus`,SERIALIZED_CLIENT_STATE:`${e}client:serializedState`},this.SERVER_INSTALL_KEY=`${e}server:installed`}getDirectStatus(){return this.getStorageValue(this.STORAGE_KEYS.DIRECT_STATUS,null)}setDirectStatus(e){this.setStorageValue(this.STORAGE_KEYS.DIRECT_STATUS,e)}clear(){try{localStorage.removeItem(this.STORAGE_KEYS.DIRECT_STATUS),localStorage.removeItem(this.STORAGE_KEYS.SERIALIZED_CLIENT_STATE),localStorage.removeItem(this.SERVER_INSTALL_KEY)}catch(e){console.warn("[BodhiClientUserPrefsManager] Failed to clear preferences:",e)}}isServerInstallConfirmed(){return this.getStorageValue(this.SERVER_INSTALL_KEY,!1)}setServerInstallConfirmed(e){this.setStorageValue(this.SERVER_INSTALL_KEY,e)}getSerializedClientState(){return this.getStorageValue(this.STORAGE_KEYS.SERIALIZED_CLIENT_STATE,null)}setSerializedClientState(e){this.setStorageValue(this.STORAGE_KEYS.SERIALIZED_CLIENT_STATE,e)}getStorageValue(e,n){try{const r=localStorage.getItem(e);return r===null?n:JSON.parse(r)}catch(r){return console.warn(`[BodhiClientUserPrefsManager] Failed to read ${e}:`,r),n}}setStorageValue(e,n){try{localStorage.setItem(e,JSON.stringify(n))}catch(r){console.warn(`[BodhiClientUserPrefsManager] Failed to write ${e}:`,r)}}}function Se(t){return t.kind==="request"}const ke={MODAL_READY:"modal:ready",MODAL_REFRESH:"modal:refresh",MODAL_CLOSE:"modal:close",MODAL_COMPLETE:"modal:complete",MODAL_LNA_CONNECT:"modal:lna:connect",MODAL_LNA_SKIP:"modal:lna:skip",MODAL_CONFIRM_SERVER_INSTALL:"modal:confirm-server-install",MODAL_SELECT_CONNECTION:"modal:select-connection",PARENT_STATE_UPDATE:"parent:state-update"},Ee=`<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
@@ -66,7 +66,7 @@ var ne={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24
|
|
|
66
66
|
<div id="root"></div>
|
|
67
67
|
</body>
|
|
68
68
|
</html>
|
|
69
|
-
`;class
|
|
69
|
+
`;class Ce{constructor(e){this.overlayElement=null,this.iframeElement=null,this.isIframeReady=!1,this.currentSetupState=null,this.messageHandler=null,this.modalHtmlPath=e.modalHtmlPath??"src/sdk/core/onboarding/modal.html",this.handlers=e.handlers}show(e){this.overlayElement||(this.currentSetupState=e,this.overlayElement=document.createElement("div"),this.overlayElement.setAttribute("data-testid","div-setup-overlay"),this.overlayElement.style.cssText=`
|
|
70
70
|
position: fixed;
|
|
71
71
|
top: 0;
|
|
72
72
|
left: 0;
|
|
@@ -77,7 +77,7 @@ var ne={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24
|
|
|
77
77
|
display: flex;
|
|
78
78
|
align-items: center;
|
|
79
79
|
justify-content: center;
|
|
80
|
-
`,this.iframeElement=document.createElement("iframe"),this.iframeElement.setAttribute("data-testid","iframe-setup"),typeof chrome<"u"&&chrome.runtime&&chrome.runtime.getURL?(this.iframeElement.sandbox.add("allow-scripts","allow-same-origin"),this.iframeElement.src=chrome.runtime.getURL(this.modalHtmlPath)):(this.iframeElement.sandbox.add("allow-scripts"),this.iframeElement.srcdoc=
|
|
80
|
+
`,this.iframeElement=document.createElement("iframe"),this.iframeElement.setAttribute("data-testid","iframe-setup"),typeof chrome<"u"&&chrome.runtime&&chrome.runtime.getURL?(this.iframeElement.sandbox.add("allow-scripts","allow-same-origin"),this.iframeElement.src=chrome.runtime.getURL(this.modalHtmlPath)):(this.iframeElement.sandbox.add("allow-scripts"),this.iframeElement.srcdoc=Ee),this.iframeElement.style.cssText=`
|
|
81
81
|
width: 90%;
|
|
82
82
|
max-width: 800px;
|
|
83
83
|
height: 90%;
|
|
@@ -85,5 +85,5 @@ var ne={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24
|
|
|
85
85
|
border: none;
|
|
86
86
|
border-radius: 8px;
|
|
87
87
|
background: white;
|
|
88
|
-
`,this.overlayElement.appendChild(this.iframeElement),document.body.appendChild(this.overlayElement),this.messageHandler=this.handleMessage.bind(this),window.addEventListener("message",this.messageHandler))}updateState(e){this.currentSetupState=e,this.sendStateToModal()}destroy(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.overlayElement&&(this.overlayElement.remove(),this.overlayElement=null,this.iframeElement=null),this.isIframeReady=!1,this.currentSetupState=null}async handleMessage(e){var a,i,s,o,l;const n=e.data;if(!
|
|
89
|
-
`);d=m.pop()||"";for(const I of m)if(I.startsWith("data: ")){const x=I.slice(6).trim();if(x==="[DONE]")return;try{yield JSON.parse(x)}catch(Y){this.logger.warn("Failed to parse SSE data:",x,Y)}}}}finally{c.releaseLock()}}async*streamChat(e,n,r=!0){yield*this.stream("POST","/v1/chat/completions",{model:e,messages:[{role:"user",content:n}],stream:!0},{},r)}async testConnectivity(){return this.ensureInitialized(),this.logger.debug("Testing connectivity to:",this.serverUrl),G(this.serverUrl)}serialize(){return this.serverUrl?{url:this.serverUrl}:{}}async debug(){return{type:"DirectClient",serverUrl:this.serverUrl,state:this.state,authState:await this.getAuthState(),authClientId:this.authClientId,authServerUrl:this.authServerUrl,userScope:this.userScope}}async getAuthState(){const e=await this._getAccessTokenRaw();return e?{isLoggedIn:!0,userInfo:S(e),accessToken:e}:{isLoggedIn:!1}}async _getAccessTokenRaw(){const e=await this._storageGet(this.storageKeys.ACCESS_TOKEN),n=await this._storageGet(this.storageKeys.EXPIRES_AT);if(!e)return null;if(n){const r=parseInt(n,10);if(Date.now()>=r-5*1e3){const a=await this._storageGet(this.storageKeys.REFRESH_TOKEN);return a?this._tryRefreshToken(a):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 n=await $(this.authEndpoints.token,e,this.authClientId);if(n){await this._storeRefreshedTokens(n);const r=S(n.access_token);return this.setAuthState({isLoggedIn:!0,userInfo:r,accessToken:n.access_token}),this.logger.info("Token refreshed successfully"),n.access_token}}catch(n){this.logger.warn("Token refresh failed:",n)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),g("Access token expired and unable to refresh. Try logging out and logging in again.","token_refresh_failed")}async _storeRefreshedTokens(e){const n=Date.now()+e.expires_in*1e3,r={[this.storageKeys.ACCESS_TOKEN]:e.access_token,[this.storageKeys.EXPIRES_AT]:String(n)};e.refresh_token&&(r[this.storageKeys.REFRESH_TOKEN]=e.refresh_token),await this._storageSet(r)}async requestResourceAccess(){const e=await this.sendApiRequest("POST","/bodhi/v1/apps/request-access",{app_client_id:this.authClientId},{},!1);if(R(e))throw new Error("Failed to get resource access scope from server");if(!O(e))throw new Error("Failed to get resource access scope from server: API error");const n=e.body.scope;return await this._storageSet({[this.storageKeys.RESOURCE_SCOPE]:n}),n}async exchangeCodeForTokens(e){const n=await this._storageGet(this.storageKeys.CODE_VERIFIER);if(!n)throw new Error("Code verifier not found");const r=this._getRedirectUri(),a=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:r,client_id:this.authClientId,code_verifier:n})});if(!a.ok){const o=await a.text();throw new Error(`Token exchange failed: ${a.status} ${o}`)}const i=await a.json(),s=Date.now()+(i.expires_in||3600)*1e3;await this._storageSet({[this.storageKeys.ACCESS_TOKEN]:i.access_token,[this.storageKeys.REFRESH_TOKEN]:i.refresh_token||"",[this.storageKeys.EXPIRES_AT]:String(s)}),await this._storageRemove([this.storageKeys.CODE_VERIFIER,this.storageKeys.STATE])}async revokeRefreshToken(){const e=await this._storageGet(this.storageKeys.REFRESH_TOKEN);if(e)try{const n=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:n})}catch(n){this.logger.warn("Token revocation failed:",n)}}async clearAuthStorage(){await this._storageRemove([this.storageKeys.ACCESS_TOKEN,this.storageKeys.REFRESH_TOKEN,this.storageKeys.EXPIRES_AT,this.storageKeys.RESOURCE_SCOPE])}}class Ie{constructor(e,n,r,a){this.connectionMode=null,this.authClientId=e,this.config=n,this.onStateChange=r??_,this.prefs=new H(a),this.logger=this.createLogger(n),this.extClient=this.createExtClient(n,i=>this.handleInternalStateChange(i)),this.directClient=this.createDirectClient(e,n,i=>this.handleInternalStateChange(i))}notifyStateChange(){this.persist(),this.onStateChange({type:"client-state",state:this.getState()}),this.getAuthState().then(e=>{this.onStateChange({type:"auth-state",state:e})}).catch(e=>{this.logger.error("Failed to get auth state after client-state change:",e)})}handleInternalStateChange(e){e.type==="client-state"?this.notifyStateChange():e.type==="auth-state"&&this.getAuthState().then(n=>{this.onStateChange({type:"auth-state",state:n})}).catch(n=>{this.logger.error("Failed to get auth state after client-state change:",n)})}serialize(){return{connectionMode:this.connectionMode,direct:this.directClient.serialize(),extension:this.extClient.serialize()}}async debug(){return{type:"FacadeClient",connectionMode:this.connectionMode,authClientId:this.authClientId,config:this.config,extClient:await this.extClient.debug(),directClient:await this.directClient.debug()}}persist(){const e=this.serialize();this.prefs.setSerializedClientState(e),this.logger.debug("Persisted state:",JSON.stringify(e,null,2))}setStateCallback(e){this.onStateChange=e}isNotSetOrDirect(){return this.connectionMode==null||this.connectionMode==="direct"}async init(e={}){const n=this.prefs.getSerializedClientState()??{connectionMode:null,direct:{},extension:{}};if(this.connectionMode===null&&n.connectionMode&&(this.connectionMode=n.connectionMode,this.logger.info("Restored connectionMode from storage:",n.connectionMode)),this.connectionMode===null)return this.logger.info("{connectionMode: null} - Eager connection detection"),await this.directClient.init({savedState:n.direct,selectedConnection:!0,testConnection:!0,serverUrl:e.serverUrl}),this.directClient.isServerReady()&&(this.connectionMode="direct",this.logger.info("Auto-detected direct connection (server ready)")),this.connectionMode===null?(await this.extClient.init({savedState:n.extension,selectedConnection:!0,testConnection:!0,timeoutMs:e.timeoutMs}),this.extClient.isServerReady()&&(this.connectionMode="extension",this.logger.info("Auto-detected extension connection (server ready)"))):await this.extClient.init({savedState:n.extension,selectedConnection:!1,testConnection:!1}),this.notifyStateChange(),this.getState();const r=this.connectionMode==="direct",a=this.connectionMode==="extension";return await this.extClient.init({savedState:n.extension,selectedConnection:a,testConnection:a&&e.testConnection,timeoutMs:e.timeoutMs}),await this.directClient.init({savedState:n.direct,selectedConnection:r,testConnection:r&&e.testConnection,serverUrl:e.serverUrl}),this.notifyStateChange(),!e.testConnection&&this.isClientInitialized()&&!this.isServerReady()&&(this.logger.info("Triggering async server state refresh"),(this.isNotSetOrDirect()?this.directClient:this.extClient).init({testConnection:!0,selectedConnection:!0}).catch(s=>{this.logger.warn("Async server state refresh failed:",s)})),this.getState()}getState(){return this.isNotSetOrDirect()?this.directClient.getState():this.extClient.getState()}isClientInitialized(){return this.isNotSetOrDirect()?this.directClient.isClientInitialized():this.extClient.isClientInitialized()}isServerReady(){return this.isNotSetOrDirect()?this.directClient.isServerReady():this.extClient.isServerReady()}sendExtRequest(e,n){if(this.isNotSetOrDirect())throw new Error("sendExtRequest not available on direct connection");return this.extClient.sendExtRequest(e,n)}sendApiRequest(e,n,r,a,i){return this.isNotSetOrDirect()?this.directClient.sendApiRequest(e,n,r,a,i):this.extClient.sendApiRequest(e,n,r,a,i)}login(){return this.isNotSetOrDirect()?this.directClient.login():this.extClient.login()}logout(){return this.isNotSetOrDirect()?this.directClient.logout():this.extClient.logout()}getAuthState(){return this.isNotSetOrDirect()?this.directClient.getAuthState():this.extClient.getAuthState()}pingApi(){return this.isNotSetOrDirect()?this.directClient.pingApi():this.extClient.pingApi()}fetchModels(){return this.isNotSetOrDirect()?this.directClient.fetchModels():this.extClient.fetchModels()}async getServerState(){return this.isNotSetOrDirect()?this.directClient.getServerState():this.extClient.getServerState()}stream(e,n,r,a,i){return this.isNotSetOrDirect()?this.directClient.stream(e,n,r,a,i):this.extClient.stream(e,n,r,a,i)}streamChat(e,n,r){return this.isNotSetOrDirect()?this.directClient.streamChat(e,n,r):this.extClient.streamChat(e,n,r)}getConnectionMode(){return this.connectionMode}async setConnectionMode(e){if(this.logger.info("Switching connection mode to:",e),e==="direct"){if(!this.directClient.isClientInitialized())throw new Error(h.SERVER_NOT_READY.message)}else if(e==="extension"){if(!this.extClient.isClientInitialized())throw new Error(h.SERVER_NOT_READY.message)}else throw new Error("Invalid connection mode");return this.connectionMode=e,this.notifyStateChange(),this.getState()}async testExtensionConnectivity(e){const n=await this.extClient.init({testConnection:!0,timeoutMs:e});return this.notifyStateChange(),n}async testDirectConnectivity(e){const n=e??this.directClient.serialize().url;if(!n)return this.directClient.getState();const r=await this.directClient.init({serverUrl:n,testConnection:!0});return this.notifyStateChange(),r}async getExtensionState(){const e=this.extClient.getState();if(b(e))return e;throw new Error("extClient did not return an ExtensionState")}async getDirectState(){const e=this.directClient.getState();if(N(e))return e;throw new Error("directClient did not return a DirectState")}}exports.AUTH_EXT_NOT_INITIALIZED=fe;exports.BACKEND_SERVER_NOT_CONNECTED=E;exports.BACKEND_SERVER_NOT_REACHABLE=y;exports.BROWSER_CONFIGS=Ce;exports.BaseFacadeClient=Ie;exports.BodhiClientUserPrefsManager=H;exports.DIRECT_STATE_NOT_INITIALIZED=v;exports.DirectClientBase=Ae;exports.EXTENSION_STATE_NOT_FOUND=D;exports.EXTENSION_STATE_NOT_INITIALIZED=M;exports.Logger=V;exports.NOOP_STATE_CALLBACK=_;exports.OS_CONFIGS=Ne;exports.OnboardingModal=Ee;exports.PENDING_EXTENSION_READY=k;exports.SERVER_ERROR_CODES=h;exports.STORAGE_PREFIXES=xe;exports.backendServerNotReady=L;exports.base64UrlEncode=A;exports.buildError=B;exports.buildEvent=F;exports.buildResponse=j;exports.createApiError=ee;exports.createDirectStateNotReachable=re;exports.createDirectStateNotReady=ae;exports.createDirectStateReady=ne;exports.createExtensionStateNotFound=oe;exports.createExtensionStateNotInitialized=se;exports.createOAuthEndpoints=W;exports.createOperationError=g;exports.createStorageKeys=Q;exports.detectBrowser=ye;exports.detectOS=be;exports.extractUserInfo=S;exports.generateCodeChallenge=je;exports.generateCodeVerifier=_e;exports.getBackendServerState=ce;exports.getExtensionId=ue;exports.getServerUrl=de;exports.handleRequest=ge;exports.isApiResultError=J;exports.isApiResultOperationError=R;exports.isApiResultSuccess=O;exports.isAuthError=pe;exports.isAuthLoggedIn=me;exports.isAuthLoggedOut=he;exports.isClientReady=le;exports.isDirectClientReady=P;exports.isDirectServerReady=te;exports.isDirectState=N;exports.isExtensionClientReady=U;exports.isExtensionServerReady=ie;exports.isExtensionState=b;exports.isOperationError=Z;exports.isServerReady=C;exports.isWebUIClient=ve;exports.parseJwt=q;exports.refreshAccessToken=$;exports.testServerConnectivity=G;
|
|
88
|
+
`,this.overlayElement.appendChild(this.iframeElement),document.body.appendChild(this.overlayElement),this.messageHandler=this.handleMessage.bind(this),window.addEventListener("message",this.messageHandler))}updateState(e){this.currentSetupState=e,this.sendStateToModal()}destroy(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.overlayElement&&(this.overlayElement.remove(),this.overlayElement=null,this.iframeElement=null),this.isIframeReady=!1,this.currentSetupState=null}async handleMessage(e){var a,i,s,o,l;const n=e.data;if(!Se(n)||e.source!==((a=this.iframeElement)==null?void 0:a.contentWindow))return;const r=this.handlers[n.type];if(!r){console.warn("[OnboardingModal] No handler for message type:",n.type);return}try{n.type===ke.MODAL_READY&&(this.isIframeReady=!0);const c=await r(n),u=j(n.requestId,n.type,c);(s=(i=this.iframeElement)==null?void 0:i.contentWindow)==null||s.postMessage(u,"*")}catch(c){console.error("[OnboardingModal] Handler error:",c);const u=F(n.requestId,{code:"handler-error",message:c instanceof Error?c.message:"Handler execution failed"});(l=(o=this.iframeElement)==null?void 0:o.contentWindow)==null||l.postMessage(u,"*")}}sendStateToModal(){var n;if(!this.isIframeReady||!this.iframeElement||!this.currentSetupState)return;const e=B("parent:state-update",{setupState:this.currentSetupState});(n=this.iframeElement.contentWindow)==null||n.postMessage(e,"*")}}const Ne=[{id:"chrome",status:"supported",name:"Google Chrome",extension_url:"https://chrome.google.com/webstore/detail/bodhi-browser/example-id"},{id:"edge",status:"supported",name:"Microsoft Edge",extension_url:"https://microsoftedge.microsoft.com/addons/detail/bodhi-browser/example-id"},{id:"firefox",status:"not-supported",name:"Mozilla Firefox",github_issue_url:"https://github.com/BodhiSearch/bodhi-browser/issues/firefox-support"},{id:"safari",status:"not-supported",name:"Safari",github_issue_url:"https://github.com/BodhiSearch/bodhi-browser/issues/safari-support"},{id:"unknown",status:"not-supported",name:"Unknown Browser",github_issue_url:"https://github.com/BodhiSearch/bodhi-browser/issues/new"}],_e=[{id:"macos",status:"supported",name:"macOS",download_url:"https://github.com/BodhiSearch/bodhi-browser/releases/latest/download/bodhi-server-macos"},{id:"windows",status:"supported",name:"Windows",download_url:"https://github.com/BodhiSearch/bodhi-browser/releases/latest/download/bodhi-server-windows.exe"},{id:"linux",status:"supported",name:"Linux",download_url:"https://github.com/BodhiSearch/bodhi-browser/releases/latest/download/bodhi-server-linux"},{id:"unknown",status:"not-supported",name:"Unknown OS",github_issue_url:"https://github.com/BodhiSearch/bodhi-browser/issues/new"}];function A(t){return btoa(String.fromCharCode(...new Uint8Array(t))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function je(){const t=new Uint8Array(32);return crypto.getRandomValues(t),A(t.buffer)}async function Ae(t){const n=new TextEncoder().encode(t),r=await crypto.subtle.digest("SHA-256",n);return A(r)}function W(t){const n=t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/"),r=decodeURIComponent(atob(n).split("").map(a=>"%"+("00"+a.charCodeAt(0).toString(16)).slice(-2)).join(""));return JSON.parse(r)}function S(t){const e=W(t);return{sub:e.sub,email:e.email,name:e.name,given_name:e.given_name,family_name:e.family_name,preferred_username:e.preferred_username}}function $(t){return{authorize:`${t}/protocol/openid-connect/auth`,token:`${t}/protocol/openid-connect/token`,revoke:`${t}/protocol/openid-connect/revoke`}}async function G(t,e,n){try{const r=await fetch(t,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",refresh_token:e,client_id:n})});if(!r.ok)return null;const a=await r.json();return{access_token:a.access_token,refresh_token:a.refresh_token,id_token:a.id_token,expires_in:a.expires_in||3600}}catch{return null}}async function Y(t){const e=`${t}/bodhi/v1/info`;try{const n=new AbortController,r=setTimeout(()=>n.abort(),5e3),a=await fetch(e,{method:"GET",headers:{"Content-Type":"application/json"},signal:n.signal});if(clearTimeout(r),a.ok&&a.status===200){const i=await a.json();return{success:!0,serverInfo:{status:i.status||"unknown",version:i.version||"unknown"}}}return{success:!1,error:{message:`Server returned ${a.status}: ${a.statusText}`,type:"server-error"}}}catch(n){return{success:!1,error:{message:`Cannot reach server: ${n instanceof Error?n.message:"Network error"}`,type:"network-error"}}}}class Ie{constructor(e,n,r){this.serverUrl=null,this.state=v,this.refreshPromise=null,this.logger=new V(n,e.logLevel),this.authClientId=e.authClientId,this.authServerUrl=e.authServerUrl||"https://id.getbodhi.app/realms/bodhi",this.userScope=e.userScope||"scope_user_user",this.authEndpoints=$(this.authServerUrl),this.storageKeys=Q(e.storagePrefix),this.onStateChange=r??_}setState(e){this.state=e,this.onStateChange({type:"client-state",state:e})}setAuthState(e){this.onStateChange({type:"auth-state",state:e})}setStateCallback(e){this.onStateChange=e}async init(e){var r;const n=e.serverUrl??((r=e.savedState)==null?void 0:r.url)??this.serverUrl;if(this.serverUrl&&this.serverUrl===n&&!e.testConnection)return this.logger.debug("Already initialized with serverUrl, skipping init"),this.state;if(this.serverUrl=n,!this.serverUrl)return this.logger.info("No serverUrl provided, returning not-initialized state"),v;if(this.logger.info("Initializing with serverUrl:",this.serverUrl),e.testConnection){const a=await this.testConnectivity();let i;if(a.success&&a.serverInfo){const s=a.serverInfo.status,o=a.serverInfo.version;s==="ready"?i={status:"ready",version:o}:s==="setup"||s==="resource-admin"||s==="error"?i=L(s,o):i=y}else this.logger.warn("Connection failed:",a.error),i=y;return this.setState({type:"direct",url:n,server:i}),this.logger.info("Initialized with testConnection, server state:",i.status),this.state}return e.selectedConnection?(this.setState({type:"direct",url:n,server:E}),this.logger.info("Initialized with selectedConnection, server state: not-connected"),this.state):(this.logger.info("No selectedConnection, returning not-initialized state"),v)}getState(){return this.state}isClientInitialized(){return this.serverUrl!==null}isServerReady(){return this.isClientInitialized()&&this.state.type==="direct"&&this.state.server.status==="ready"}ensureInitialized(){if(!this.serverUrl)throw g("DirectClient not initialized. Call init(serverUrl) first.","not-initialized")}async sendApiRequest(e,n,r,a,i=!0){if(!this.serverUrl)return{error:{message:"Client not initialized - connection failed",type:"not-initialized"}};const s=`${this.serverUrl}${n}`;this.logger.debug(`${e} ${s}`);try{const o=new AbortController,l=setTimeout(()=>o.abort(),5e3),c={"Content-Type":"application/json",...a};if(i){const f=await this._getAccessTokenRaw();f&&(c.Authorization=`Bearer ${f}`)}const u=await fetch(s,{method:e,headers:c,body:r?JSON.stringify(r):void 0,signal:o.signal});clearTimeout(l);const d={};return u.headers.forEach((f,m)=>{d[m]=f}),{body:await u.json(),status:u.status,headers:d}}catch(o){return{error:{message:`Network error: ${o instanceof Error?o.message:"Unknown error"}`,type:"network_error"}}}}async pingApi(){return this.sendApiRequest("GET","/ping",void 0,{},!1)}async fetchModels(){return this.sendApiRequest("GET","/v1/models")}async getServerState(){const e=await this.testConnectivity();if(!e.success)return{status:"not-reachable",error:e.error||{message:"Connection failed",type:"network_error"}};const n=e.serverInfo;switch(n.status){case"ready":return{status:"ready",version:n.version};case"setup":return{status:"setup",version:n.version,error:{message:"Setup required",type:"extension_error"}};case"resource-admin":return{status:"resource-admin",version:n.version,error:{message:"Resource admin required",type:"extension_error"}};case"error":return{status:"error",version:n.version||"unknown",error:{message:"Server error",type:"extension_error"}};default:return{status:"not-reachable",error:{message:"Unknown status",type:"extension_error"}}}}async*stream(e,n,r,a,i=!0){if(!this.serverUrl)throw g("Client not initialized - connection failed","not-initialized");const s=`${this.serverUrl}${n}`;this.logger.debug(`Stream ${e} ${s}`);const o={"Content-Type":"application/json",Accept:"text/event-stream",...a};if(i){const p=await this._getAccessTokenRaw();p&&(o.Authorization=`Bearer ${p}`)}const l=await fetch(s,{method:e,headers:o,body:r?JSON.stringify(r):void 0});if(!l.ok)throw new Error(`HTTP ${l.status}: ${await l.text()}`);if(!l.body)throw new Error("Response body is null");const c=l.body.getReader(),u=new TextDecoder;let d="";try{for(;;){const{done:p,value:f}=await c.read();if(p)break;d+=u.decode(f,{stream:!0});const m=d.split(`
|
|
89
|
+
`);d=m.pop()||"";for(const I of m)if(I.startsWith("data: ")){const x=I.slice(6).trim();if(x==="[DONE]")return;try{yield JSON.parse(x)}catch(X){this.logger.warn("Failed to parse SSE data:",x,X)}}}}finally{c.releaseLock()}}async*streamChat(e,n,r=!0){yield*this.stream("POST","/v1/chat/completions",{model:e,messages:[{role:"user",content:n}],stream:!0},{},r)}async testConnectivity(){return this.ensureInitialized(),this.logger.debug("Testing connectivity to:",this.serverUrl),Y(this.serverUrl)}serialize(){return this.serverUrl?{url:this.serverUrl}:{}}async debug(){return{type:"DirectClient",serverUrl:this.serverUrl,state:this.state,authState:await this.getAuthState(),authClientId:this.authClientId,authServerUrl:this.authServerUrl,userScope:this.userScope}}async getAuthState(){const e=await this._getAccessTokenRaw();return e?{isLoggedIn:!0,userInfo:S(e),accessToken:e}:{isLoggedIn:!1}}async _getAccessTokenRaw(){const e=await this._storageGet(this.storageKeys.ACCESS_TOKEN),n=await this._storageGet(this.storageKeys.EXPIRES_AT);if(!e)return null;if(n){const r=parseInt(n,10);if(Date.now()>=r-5*1e3){const a=await this._storageGet(this.storageKeys.REFRESH_TOKEN);return a?this._tryRefreshToken(a):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 n=await G(this.authEndpoints.token,e,this.authClientId);if(n){await this._storeRefreshedTokens(n);const r=S(n.access_token);return this.setAuthState({isLoggedIn:!0,userInfo:r,accessToken:n.access_token}),this.logger.info("Token refreshed successfully"),n.access_token}}catch(n){this.logger.warn("Token refresh failed:",n)}throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),g("Access token expired and unable to refresh. Try logging out and logging in again.","token_refresh_failed")}async _storeRefreshedTokens(e){const n=Date.now()+e.expires_in*1e3,r={[this.storageKeys.ACCESS_TOKEN]:e.access_token,[this.storageKeys.EXPIRES_AT]:String(n)};e.refresh_token&&(r[this.storageKeys.REFRESH_TOKEN]=e.refresh_token),await this._storageSet(r)}async requestResourceAccess(){const e=await this.sendApiRequest("POST","/bodhi/v1/apps/request-access",{app_client_id:this.authClientId},{},!1);if(R(e))throw new Error("Failed to get resource access scope from server");if(!O(e))throw new Error("Failed to get resource access scope from server: API error");const n=e.body.scope;return await this._storageSet({[this.storageKeys.RESOURCE_SCOPE]:n}),n}async exchangeCodeForTokens(e){const n=await this._storageGet(this.storageKeys.CODE_VERIFIER);if(!n)throw new Error("Code verifier not found");const r=this._getRedirectUri(),a=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:r,client_id:this.authClientId,code_verifier:n})});if(!a.ok){const o=await a.text();throw new Error(`Token exchange failed: ${a.status} ${o}`)}const i=await a.json(),s=Date.now()+(i.expires_in||3600)*1e3;await this._storageSet({[this.storageKeys.ACCESS_TOKEN]:i.access_token,[this.storageKeys.REFRESH_TOKEN]:i.refresh_token||"",[this.storageKeys.EXPIRES_AT]:String(s)}),await this._storageRemove([this.storageKeys.CODE_VERIFIER,this.storageKeys.STATE])}async revokeRefreshToken(){const e=await this._storageGet(this.storageKeys.REFRESH_TOKEN);if(e)try{const n=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:n})}catch(n){this.logger.warn("Token revocation failed:",n)}}async clearAuthStorage(){await this._storageRemove([this.storageKeys.ACCESS_TOKEN,this.storageKeys.REFRESH_TOKEN,this.storageKeys.EXPIRES_AT,this.storageKeys.RESOURCE_SCOPE])}}class Te{constructor(e,n,r,a,i){this.connectionMode=null,this.authClientId=e,this.config=n,this.onStateChange=r??_;const s=H(i||"/",a||"bodhijs:");this.prefs=new q(s),this.logger=this.createLogger(n),this.extClient=this.createExtClient(n,o=>this.handleInternalStateChange(o)),this.directClient=this.createDirectClient(e,n,o=>this.handleInternalStateChange(o))}notifyStateChange(){this.persist(),this.onStateChange({type:"client-state",state:this.getState()}),this.getAuthState().then(e=>{this.onStateChange({type:"auth-state",state:e})}).catch(e=>{this.logger.error("Failed to get auth state after client-state change:",e)})}handleInternalStateChange(e){e.type==="client-state"?this.notifyStateChange():e.type==="auth-state"&&this.getAuthState().then(n=>{this.onStateChange({type:"auth-state",state:n})}).catch(n=>{this.logger.error("Failed to get auth state after client-state change:",n)})}serialize(){return{connectionMode:this.connectionMode,direct:this.directClient.serialize(),extension:this.extClient.serialize()}}async debug(){return{type:"FacadeClient",connectionMode:this.connectionMode,authClientId:this.authClientId,config:this.config,extClient:await this.extClient.debug(),directClient:await this.directClient.debug()}}persist(){const e=this.serialize();this.prefs.setSerializedClientState(e),this.logger.debug("Persisted state:",JSON.stringify(e,null,2))}setStateCallback(e){this.onStateChange=e}isNotSetOrDirect(){return this.connectionMode==null||this.connectionMode==="direct"}async init(e={}){const n=this.prefs.getSerializedClientState()??{connectionMode:null,direct:{},extension:{}};if(this.connectionMode===null&&n.connectionMode&&(this.connectionMode=n.connectionMode,this.logger.info("Restored connectionMode from storage:",n.connectionMode)),this.connectionMode===null)return this.logger.info("{connectionMode: null} - Eager connection detection"),await this.directClient.init({savedState:n.direct,selectedConnection:!0,testConnection:!0,serverUrl:e.serverUrl}),this.directClient.isServerReady()&&(this.connectionMode="direct",this.logger.info("Auto-detected direct connection (server ready)")),this.connectionMode===null?(await this.extClient.init({savedState:n.extension,selectedConnection:!0,testConnection:!0,timeoutMs:e.timeoutMs}),this.extClient.isServerReady()&&(this.connectionMode="extension",this.logger.info("Auto-detected extension connection (server ready)"))):await this.extClient.init({savedState:n.extension,selectedConnection:!1,testConnection:!1}),this.notifyStateChange(),this.getState();const r=this.connectionMode==="direct",a=this.connectionMode==="extension";return await this.extClient.init({savedState:n.extension,selectedConnection:a,testConnection:a&&e.testConnection,timeoutMs:e.timeoutMs}),await this.directClient.init({savedState:n.direct,selectedConnection:r,testConnection:r&&e.testConnection,serverUrl:e.serverUrl}),this.notifyStateChange(),!e.testConnection&&this.isClientInitialized()&&!this.isServerReady()&&(this.logger.info("Triggering async server state refresh"),(this.isNotSetOrDirect()?this.directClient:this.extClient).init({testConnection:!0,selectedConnection:!0}).catch(s=>{this.logger.warn("Async server state refresh failed:",s)})),this.getState()}getState(){return this.isNotSetOrDirect()?this.directClient.getState():this.extClient.getState()}isClientInitialized(){return this.isNotSetOrDirect()?this.directClient.isClientInitialized():this.extClient.isClientInitialized()}isServerReady(){return this.isNotSetOrDirect()?this.directClient.isServerReady():this.extClient.isServerReady()}sendExtRequest(e,n){if(this.isNotSetOrDirect())throw new Error("sendExtRequest not available on direct connection");return this.extClient.sendExtRequest(e,n)}sendApiRequest(e,n,r,a,i){return this.isNotSetOrDirect()?this.directClient.sendApiRequest(e,n,r,a,i):this.extClient.sendApiRequest(e,n,r,a,i)}login(){return this.isNotSetOrDirect()?this.directClient.login():this.extClient.login()}logout(){return this.isNotSetOrDirect()?this.directClient.logout():this.extClient.logout()}getAuthState(){return this.isNotSetOrDirect()?this.directClient.getAuthState():this.extClient.getAuthState()}pingApi(){return this.isNotSetOrDirect()?this.directClient.pingApi():this.extClient.pingApi()}fetchModels(){return this.isNotSetOrDirect()?this.directClient.fetchModels():this.extClient.fetchModels()}async getServerState(){return this.isNotSetOrDirect()?this.directClient.getServerState():this.extClient.getServerState()}stream(e,n,r,a,i){return this.isNotSetOrDirect()?this.directClient.stream(e,n,r,a,i):this.extClient.stream(e,n,r,a,i)}streamChat(e,n,r){return this.isNotSetOrDirect()?this.directClient.streamChat(e,n,r):this.extClient.streamChat(e,n,r)}getConnectionMode(){return this.connectionMode}async setConnectionMode(e){if(this.logger.info("Switching connection mode to:",e),e==="direct"){if(!this.directClient.isClientInitialized())throw new Error(h.SERVER_NOT_READY.message)}else if(e==="extension"){if(!this.extClient.isClientInitialized())throw new Error(h.SERVER_NOT_READY.message)}else throw new Error("Invalid connection mode");return this.connectionMode=e,this.notifyStateChange(),this.getState()}async testExtensionConnectivity(e){const n=await this.extClient.init({testConnection:!0,timeoutMs:e});return this.notifyStateChange(),n}async testDirectConnectivity(e){const n=e??this.directClient.serialize().url;if(!n)return this.directClient.getState();const r=await this.directClient.init({serverUrl:n,testConnection:!0});return this.notifyStateChange(),r}async getExtensionState(){const e=this.extClient.getState();if(b(e))return e;throw new Error("extClient did not return an ExtensionState")}async getDirectState(){const e=this.directClient.getState();if(N(e))return e;throw new Error("directClient did not return a DirectState")}}const ze="production";exports.AUTH_EXT_NOT_INITIALIZED=pe;exports.BACKEND_SERVER_NOT_CONNECTED=E;exports.BACKEND_SERVER_NOT_REACHABLE=y;exports.BROWSER_CONFIGS=Ne;exports.BaseFacadeClient=Te;exports.BodhiClientUserPrefsManager=q;exports.CORE_BUILD_MODE=ze;exports.DIRECT_STATE_NOT_INITIALIZED=v;exports.DirectClientBase=Ie;exports.EXTENSION_STATE_NOT_FOUND=D;exports.EXTENSION_STATE_NOT_INITIALIZED=M;exports.Logger=V;exports.NOOP_STATE_CALLBACK=_;exports.OS_CONFIGS=_e;exports.OnboardingModal=Ce;exports.PENDING_EXTENSION_READY=k;exports.SERVER_ERROR_CODES=h;exports.STORAGE_PREFIXES=we;exports.backendServerNotReady=L;exports.base64UrlEncode=A;exports.buildError=F;exports.buildEvent=B;exports.buildResponse=j;exports.createApiError=te;exports.createDirectStateNotReachable=ae;exports.createDirectStateNotReady=ie;exports.createDirectStateReady=re;exports.createExtensionStateNotFound=le;exports.createExtensionStateNotInitialized=oe;exports.createOAuthEndpoints=$;exports.createOperationError=g;exports.createStorageKeys=Q;exports.createStoragePrefixWithBasePath=H;exports.detectBrowser=be;exports.detectOS=xe;exports.extractUserInfo=S;exports.generateCodeChallenge=Ae;exports.generateCodeVerifier=je;exports.getBackendServerState=ue;exports.getExtensionId=de;exports.getServerUrl=fe;exports.handleRequest=ve;exports.isApiResultError=ee;exports.isApiResultOperationError=R;exports.isApiResultSuccess=O;exports.isAuthError=he;exports.isAuthLoggedIn=ge;exports.isAuthLoggedOut=me;exports.isClientReady=ce;exports.isDirectClientReady=P;exports.isDirectServerReady=ne;exports.isDirectState=N;exports.isExtensionClientReady=U;exports.isExtensionServerReady=se;exports.isExtensionState=b;exports.isOperationError=J;exports.isServerReady=C;exports.isWebUIClient=ye;exports.parseJwt=W;exports.refreshAccessToken=G;exports.testServerConnectivity=Y;
|
package/dist/bodhi-core.esm.js
CHANGED
|
@@ -8,7 +8,7 @@ function O(t) {
|
|
|
8
8
|
function N(t) {
|
|
9
9
|
return b(t) && "message" in t && typeof t.message == "string" && "type" in t && typeof t.type == "string";
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function re(t) {
|
|
12
12
|
return t instanceof Error && "error" in t && !("response" in t) && N(t.error);
|
|
13
13
|
}
|
|
14
14
|
function L(t) {
|
|
@@ -17,10 +17,10 @@ function L(t) {
|
|
|
17
17
|
function P(t) {
|
|
18
18
|
return "body" in t && "status" in t && typeof t.status == "number" && t.status >= 200 && t.status < 300;
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function ae(t) {
|
|
21
21
|
return "body" in t && "status" in t && typeof t.status == "number" && t.status >= 400 && O(t.body);
|
|
22
22
|
}
|
|
23
|
-
const
|
|
23
|
+
const ie = (t, e, n, r) => {
|
|
24
24
|
const a = new Error(t);
|
|
25
25
|
return a.response = { status: e, body: n, headers: r }, a;
|
|
26
26
|
}, v = (t, e) => {
|
|
@@ -59,7 +59,7 @@ function w(t) {
|
|
|
59
59
|
function I(t) {
|
|
60
60
|
return t.type === "direct";
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function se(t) {
|
|
63
63
|
return typeof t.server == "object" && t.server.status !== "not-connected" && A(t.server);
|
|
64
64
|
}
|
|
65
65
|
function D(t) {
|
|
@@ -69,13 +69,13 @@ const y = {
|
|
|
69
69
|
type: "direct",
|
|
70
70
|
server: j
|
|
71
71
|
};
|
|
72
|
-
function
|
|
72
|
+
function oe(t, e = "unknown") {
|
|
73
73
|
return { type: "direct", server: { status: "ready", version: e }, url: t };
|
|
74
74
|
}
|
|
75
|
-
function
|
|
75
|
+
function le(t) {
|
|
76
76
|
return { type: "direct", server: x, url: t };
|
|
77
77
|
}
|
|
78
|
-
function
|
|
78
|
+
function ce(t, e) {
|
|
79
79
|
return { type: "direct", server: e, url: t };
|
|
80
80
|
}
|
|
81
81
|
const U = {
|
|
@@ -93,38 +93,38 @@ function ue(t) {
|
|
|
93
93
|
function B(t) {
|
|
94
94
|
return t.extension === "ready" && "extensionId" in t;
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function de() {
|
|
97
97
|
return U;
|
|
98
98
|
}
|
|
99
|
-
function
|
|
99
|
+
function fe() {
|
|
100
100
|
return F;
|
|
101
101
|
}
|
|
102
|
-
function
|
|
102
|
+
function pe(t) {
|
|
103
103
|
return w(t) ? B(t) : D(t);
|
|
104
104
|
}
|
|
105
|
-
function
|
|
105
|
+
function he(t) {
|
|
106
106
|
return t.server;
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function me(t) {
|
|
109
109
|
return w(t) && t.extension === "ready" ? t.extensionId : void 0;
|
|
110
110
|
}
|
|
111
|
-
function
|
|
111
|
+
function ge(t) {
|
|
112
112
|
return I(t) && "url" in t ? t.url : void 0;
|
|
113
113
|
}
|
|
114
|
-
const
|
|
114
|
+
const ve = {
|
|
115
115
|
isLoggedIn: !1,
|
|
116
116
|
error: {
|
|
117
117
|
message: "Client not initialized",
|
|
118
118
|
code: "CLIENT_NOT_INITIALIZED"
|
|
119
119
|
}
|
|
120
120
|
};
|
|
121
|
-
function
|
|
121
|
+
function ye(t) {
|
|
122
122
|
return typeof t == "object" && t !== null && "isLoggedIn" in t && t.isLoggedIn === !1 && "error" in t && typeof t.error == "object" && t.error !== null && "message" in t.error && typeof t.error.message == "string" && "code" in t.error && typeof t.error.code == "string";
|
|
123
123
|
}
|
|
124
|
-
function
|
|
124
|
+
function be(t) {
|
|
125
125
|
return typeof t == "object" && t !== null && "isLoggedIn" in t && t.isLoggedIn === !1 && !("error" in t);
|
|
126
126
|
}
|
|
127
|
-
function
|
|
127
|
+
function xe(t) {
|
|
128
128
|
return typeof t == "object" && t !== null && "isLoggedIn" in t && t.isLoggedIn === !0 && "userInfo" in t && typeof t.userInfo == "object" && t.userInfo !== null && "sub" in t.userInfo && typeof t.userInfo.sub == "string" && "accessToken" in t && typeof t.accessToken == "string";
|
|
129
129
|
}
|
|
130
130
|
const z = () => {
|
|
@@ -138,7 +138,7 @@ function K(t, e, n) {
|
|
|
138
138
|
function Q(t, e) {
|
|
139
139
|
return { kind: "error", requestId: t, error: e };
|
|
140
140
|
}
|
|
141
|
-
function
|
|
141
|
+
function we(t, e) {
|
|
142
142
|
const n = e[t.type];
|
|
143
143
|
if (!n) return null;
|
|
144
144
|
const r = n(t.payload);
|
|
@@ -175,10 +175,10 @@ class H {
|
|
|
175
175
|
this.shouldLog("error") && console.error(`[${this.prefix}] ${this.ts()}`, ...e);
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
function
|
|
178
|
+
function Se(t) {
|
|
179
179
|
return "handleOAuthCallback" in t;
|
|
180
180
|
}
|
|
181
|
-
function
|
|
181
|
+
function ke() {
|
|
182
182
|
var a;
|
|
183
183
|
const e = new C().getBrowser(), n = ((a = e.name) == null ? void 0 : a.toLowerCase()) || "", r = e.name || "Unknown Browser";
|
|
184
184
|
if (n.includes("chrome"))
|
|
@@ -194,7 +194,7 @@ function Se() {
|
|
|
194
194
|
return (!i || i.toLowerCase() === "unknown") && (i = "Unknown Browser"), { name: i, type: "unknown" };
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
|
-
function
|
|
197
|
+
function Ee() {
|
|
198
198
|
var r;
|
|
199
199
|
const n = ((r = new C().getOS().name) == null ? void 0 : r.toLowerCase()) || "";
|
|
200
200
|
return n.includes("mac") ? { name: "macOS", type: "macos" } : n.includes("windows") ? { name: "Windows", type: "windows" } : n.includes("linux") || n.includes("ubuntu") || n.includes("fedora") || n.includes("debian") ? { name: "Linux", type: "linux" } : { name: "Unknown", type: "unknown" };
|
|
@@ -209,12 +209,15 @@ function q(t) {
|
|
|
209
209
|
RESOURCE_SCOPE: `${t}:resource_scope`
|
|
210
210
|
};
|
|
211
211
|
}
|
|
212
|
-
const
|
|
212
|
+
const Ce = {
|
|
213
213
|
DIRECT: "bodhi:direct",
|
|
214
214
|
WEB: "bodhi:web",
|
|
215
215
|
EXT: "bodhi:ext"
|
|
216
216
|
};
|
|
217
|
-
|
|
217
|
+
function W(t, e) {
|
|
218
|
+
return `${t}:${e}`;
|
|
219
|
+
}
|
|
220
|
+
class $ {
|
|
218
221
|
/**
|
|
219
222
|
* @param storagePrefix - Prefix for localStorage keys (default: 'bodhijs:')
|
|
220
223
|
*/
|
|
@@ -291,10 +294,10 @@ class W {
|
|
|
291
294
|
}
|
|
292
295
|
}
|
|
293
296
|
}
|
|
294
|
-
function
|
|
297
|
+
function Y(t) {
|
|
295
298
|
return t.kind === "request";
|
|
296
299
|
}
|
|
297
|
-
const
|
|
300
|
+
const G = {
|
|
298
301
|
// Modal lifecycle
|
|
299
302
|
MODAL_READY: "modal:ready",
|
|
300
303
|
MODAL_REFRESH: "modal:refresh",
|
|
@@ -309,7 +312,7 @@ const Y = {
|
|
|
309
312
|
MODAL_SELECT_CONNECTION: "modal:select-connection",
|
|
310
313
|
// Parent → Modal events
|
|
311
314
|
PARENT_STATE_UPDATE: "parent:state-update"
|
|
312
|
-
},
|
|
315
|
+
}, X = `<!doctype html>
|
|
313
316
|
<html lang="en">
|
|
314
317
|
<head>
|
|
315
318
|
<meta charset="UTF-8" />
|
|
@@ -378,7 +381,7 @@ var ne={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24
|
|
|
378
381
|
</body>
|
|
379
382
|
</html>
|
|
380
383
|
`;
|
|
381
|
-
class
|
|
384
|
+
class Ne {
|
|
382
385
|
constructor(e) {
|
|
383
386
|
this.overlayElement = null, this.iframeElement = null, this.isIframeReady = !1, this.currentSetupState = null, this.messageHandler = null, this.modalHtmlPath = e.modalHtmlPath ?? "src/sdk/core/onboarding/modal.html", this.handlers = e.handlers;
|
|
384
387
|
}
|
|
@@ -398,7 +401,7 @@ class Ce {
|
|
|
398
401
|
display: flex;
|
|
399
402
|
align-items: center;
|
|
400
403
|
justify-content: center;
|
|
401
|
-
`, this.iframeElement = document.createElement("iframe"), this.iframeElement.setAttribute("data-testid", "iframe-setup"), typeof chrome < "u" && chrome.runtime && chrome.runtime.getURL ? (this.iframeElement.sandbox.add("allow-scripts", "allow-same-origin"), this.iframeElement.src = chrome.runtime.getURL(this.modalHtmlPath)) : (this.iframeElement.sandbox.add("allow-scripts"), this.iframeElement.srcdoc =
|
|
404
|
+
`, this.iframeElement = document.createElement("iframe"), this.iframeElement.setAttribute("data-testid", "iframe-setup"), typeof chrome < "u" && chrome.runtime && chrome.runtime.getURL ? (this.iframeElement.sandbox.add("allow-scripts", "allow-same-origin"), this.iframeElement.src = chrome.runtime.getURL(this.modalHtmlPath)) : (this.iframeElement.sandbox.add("allow-scripts"), this.iframeElement.srcdoc = X), this.iframeElement.style.cssText = `
|
|
402
405
|
width: 90%;
|
|
403
406
|
max-width: 800px;
|
|
404
407
|
height: 90%;
|
|
@@ -428,7 +431,7 @@ class Ce {
|
|
|
428
431
|
async handleMessage(e) {
|
|
429
432
|
var a, i, s, o, l;
|
|
430
433
|
const n = e.data;
|
|
431
|
-
if (
|
|
434
|
+
if (!Y(n) || e.source !== ((a = this.iframeElement) == null ? void 0 : a.contentWindow))
|
|
432
435
|
return;
|
|
433
436
|
const r = this.handlers[n.type];
|
|
434
437
|
if (!r) {
|
|
@@ -436,16 +439,16 @@ class Ce {
|
|
|
436
439
|
return;
|
|
437
440
|
}
|
|
438
441
|
try {
|
|
439
|
-
n.type ===
|
|
440
|
-
const
|
|
441
|
-
(s = (i = this.iframeElement) == null ? void 0 : i.contentWindow) == null || s.postMessage(
|
|
442
|
-
} catch (
|
|
443
|
-
console.error("[OnboardingModal] Handler error:",
|
|
444
|
-
const
|
|
442
|
+
n.type === G.MODAL_READY && (this.isIframeReady = !0);
|
|
443
|
+
const c = await r(n), u = K(n.requestId, n.type, c);
|
|
444
|
+
(s = (i = this.iframeElement) == null ? void 0 : i.contentWindow) == null || s.postMessage(u, "*");
|
|
445
|
+
} catch (c) {
|
|
446
|
+
console.error("[OnboardingModal] Handler error:", c);
|
|
447
|
+
const u = Q(n.requestId, {
|
|
445
448
|
code: "handler-error",
|
|
446
|
-
message:
|
|
449
|
+
message: c instanceof Error ? c.message : "Handler execution failed"
|
|
447
450
|
});
|
|
448
|
-
(l = (o = this.iframeElement) == null ? void 0 : o.contentWindow) == null || l.postMessage(
|
|
451
|
+
(l = (o = this.iframeElement) == null ? void 0 : o.contentWindow) == null || l.postMessage(u, "*");
|
|
449
452
|
}
|
|
450
453
|
}
|
|
451
454
|
/**
|
|
@@ -461,7 +464,7 @@ class Ce {
|
|
|
461
464
|
(n = this.iframeElement.contentWindow) == null || n.postMessage(e, "*");
|
|
462
465
|
}
|
|
463
466
|
}
|
|
464
|
-
const
|
|
467
|
+
const _e = [
|
|
465
468
|
{
|
|
466
469
|
id: "chrome",
|
|
467
470
|
status: "supported",
|
|
@@ -492,7 +495,7 @@ const Ne = [
|
|
|
492
495
|
name: "Unknown Browser",
|
|
493
496
|
github_issue_url: "https://github.com/BodhiSearch/bodhi-browser/issues/new"
|
|
494
497
|
}
|
|
495
|
-
],
|
|
498
|
+
], je = [
|
|
496
499
|
{
|
|
497
500
|
id: "macos",
|
|
498
501
|
status: "supported",
|
|
@@ -521,22 +524,22 @@ const Ne = [
|
|
|
521
524
|
function T(t) {
|
|
522
525
|
return btoa(String.fromCharCode(...new Uint8Array(t))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
523
526
|
}
|
|
524
|
-
function
|
|
527
|
+
function Ae() {
|
|
525
528
|
const t = new Uint8Array(32);
|
|
526
529
|
return crypto.getRandomValues(t), T(t.buffer);
|
|
527
530
|
}
|
|
528
|
-
async function
|
|
531
|
+
async function Ie(t) {
|
|
529
532
|
const n = new TextEncoder().encode(t), r = await crypto.subtle.digest("SHA-256", n);
|
|
530
533
|
return T(r);
|
|
531
534
|
}
|
|
532
|
-
function
|
|
535
|
+
function Z(t) {
|
|
533
536
|
const n = t.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), r = decodeURIComponent(
|
|
534
537
|
atob(n).split("").map((a) => "%" + ("00" + a.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
535
538
|
);
|
|
536
539
|
return JSON.parse(r);
|
|
537
540
|
}
|
|
538
541
|
function E(t) {
|
|
539
|
-
const e =
|
|
542
|
+
const e = Z(t);
|
|
540
543
|
return {
|
|
541
544
|
sub: e.sub,
|
|
542
545
|
email: e.email,
|
|
@@ -546,14 +549,14 @@ function E(t) {
|
|
|
546
549
|
preferred_username: e.preferred_username
|
|
547
550
|
};
|
|
548
551
|
}
|
|
549
|
-
function
|
|
552
|
+
function J(t) {
|
|
550
553
|
return {
|
|
551
554
|
authorize: `${t}/protocol/openid-connect/auth`,
|
|
552
555
|
token: `${t}/protocol/openid-connect/token`,
|
|
553
556
|
revoke: `${t}/protocol/openid-connect/revoke`
|
|
554
557
|
};
|
|
555
558
|
}
|
|
556
|
-
async function
|
|
559
|
+
async function ee(t, e, n) {
|
|
557
560
|
try {
|
|
558
561
|
const r = await fetch(t, {
|
|
559
562
|
method: "POST",
|
|
@@ -577,7 +580,7 @@ async function J(t, e, n) {
|
|
|
577
580
|
return null;
|
|
578
581
|
}
|
|
579
582
|
}
|
|
580
|
-
async function
|
|
583
|
+
async function te(t) {
|
|
581
584
|
const e = `${t}/bodhi/v1/info`;
|
|
582
585
|
try {
|
|
583
586
|
const n = new AbortController(), r = setTimeout(() => n.abort(), 5e3), a = await fetch(e, {
|
|
@@ -612,9 +615,9 @@ async function ee(t) {
|
|
|
612
615
|
};
|
|
613
616
|
}
|
|
614
617
|
}
|
|
615
|
-
class
|
|
618
|
+
class ze {
|
|
616
619
|
constructor(e, n, r) {
|
|
617
|
-
this.serverUrl = null, this.state = y, this.refreshPromise = null, this.logger = new H(n, e.logLevel), this.authClientId = e.authClientId, this.authServerUrl = e.authServerUrl || "https://id.getbodhi.app/realms/bodhi", this.userScope = e.userScope || "scope_user_user", this.authEndpoints =
|
|
620
|
+
this.serverUrl = null, this.state = y, this.refreshPromise = null, this.logger = new H(n, e.logLevel), this.authClientId = e.authClientId, this.authServerUrl = e.authServerUrl || "https://id.getbodhi.app/realms/bodhi", this.userScope = e.userScope || "scope_user_user", this.authEndpoints = J(this.authServerUrl), this.storageKeys = q(e.storagePrefix), this.onStateChange = r ?? z;
|
|
618
621
|
}
|
|
619
622
|
/**
|
|
620
623
|
* Set client state and notify callback
|
|
@@ -689,27 +692,27 @@ class Ie {
|
|
|
689
692
|
const s = `${this.serverUrl}${n}`;
|
|
690
693
|
this.logger.debug(`${e} ${s}`);
|
|
691
694
|
try {
|
|
692
|
-
const o = new AbortController(), l = setTimeout(() => o.abort(), 5e3),
|
|
695
|
+
const o = new AbortController(), l = setTimeout(() => o.abort(), 5e3), c = {
|
|
693
696
|
"Content-Type": "application/json",
|
|
694
697
|
...a
|
|
695
698
|
};
|
|
696
699
|
if (i) {
|
|
697
700
|
const f = await this._getAccessTokenRaw();
|
|
698
|
-
f && (
|
|
701
|
+
f && (c.Authorization = `Bearer ${f}`);
|
|
699
702
|
}
|
|
700
|
-
const
|
|
703
|
+
const u = await fetch(s, {
|
|
701
704
|
method: e,
|
|
702
|
-
headers:
|
|
705
|
+
headers: c,
|
|
703
706
|
body: r ? JSON.stringify(r) : void 0,
|
|
704
707
|
signal: o.signal
|
|
705
708
|
});
|
|
706
709
|
clearTimeout(l);
|
|
707
710
|
const d = {};
|
|
708
|
-
return
|
|
711
|
+
return u.headers.forEach((f, h) => {
|
|
709
712
|
d[h] = f;
|
|
710
713
|
}), {
|
|
711
|
-
body: await
|
|
712
|
-
status:
|
|
714
|
+
body: await u.json(),
|
|
715
|
+
status: u.status,
|
|
713
716
|
headers: d
|
|
714
717
|
};
|
|
715
718
|
} catch (o) {
|
|
@@ -793,13 +796,13 @@ class Ie {
|
|
|
793
796
|
throw new Error(`HTTP ${l.status}: ${await l.text()}`);
|
|
794
797
|
if (!l.body)
|
|
795
798
|
throw new Error("Response body is null");
|
|
796
|
-
const
|
|
799
|
+
const c = l.body.getReader(), u = new TextDecoder();
|
|
797
800
|
let d = "";
|
|
798
801
|
try {
|
|
799
802
|
for (; ; ) {
|
|
800
|
-
const { done: p, value: f } = await
|
|
803
|
+
const { done: p, value: f } = await c.read();
|
|
801
804
|
if (p) break;
|
|
802
|
-
d +=
|
|
805
|
+
d += u.decode(f, { stream: !0 });
|
|
803
806
|
const h = d.split(`
|
|
804
807
|
`);
|
|
805
808
|
d = h.pop() || "";
|
|
@@ -816,7 +819,7 @@ class Ie {
|
|
|
816
819
|
}
|
|
817
820
|
}
|
|
818
821
|
} finally {
|
|
819
|
-
|
|
822
|
+
c.releaseLock();
|
|
820
823
|
}
|
|
821
824
|
}
|
|
822
825
|
async *streamChat(e, n, r = !0) {
|
|
@@ -839,7 +842,7 @@ class Ie {
|
|
|
839
842
|
* Test connectivity to local server
|
|
840
843
|
*/
|
|
841
844
|
async testConnectivity() {
|
|
842
|
-
return this.ensureInitialized(), this.logger.debug("Testing connectivity to:", this.serverUrl),
|
|
845
|
+
return this.ensureInitialized(), this.logger.debug("Testing connectivity to:", this.serverUrl), te(this.serverUrl);
|
|
843
846
|
}
|
|
844
847
|
// ============================================================================
|
|
845
848
|
// Serialization
|
|
@@ -900,7 +903,7 @@ class Ie {
|
|
|
900
903
|
async _doRefreshToken(e) {
|
|
901
904
|
this.logger.debug("Refreshing access token");
|
|
902
905
|
try {
|
|
903
|
-
const n = await
|
|
906
|
+
const n = await ee(
|
|
904
907
|
this.authEndpoints.token,
|
|
905
908
|
e,
|
|
906
909
|
this.authClientId
|
|
@@ -1003,15 +1006,20 @@ class Ie {
|
|
|
1003
1006
|
]);
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
|
-
class
|
|
1007
|
-
constructor(e, n, r, a) {
|
|
1008
|
-
this.connectionMode = null, this.authClientId = e, this.config = n, this.onStateChange = r ?? z
|
|
1009
|
+
class Ke {
|
|
1010
|
+
constructor(e, n, r, a, i) {
|
|
1011
|
+
this.connectionMode = null, this.authClientId = e, this.config = n, this.onStateChange = r ?? z;
|
|
1012
|
+
const s = W(
|
|
1013
|
+
i || "/",
|
|
1014
|
+
a || "bodhijs:"
|
|
1015
|
+
);
|
|
1016
|
+
this.prefs = new $(s), this.logger = this.createLogger(n), this.extClient = this.createExtClient(
|
|
1009
1017
|
n,
|
|
1010
|
-
(
|
|
1018
|
+
(o) => this.handleInternalStateChange(o)
|
|
1011
1019
|
), this.directClient = this.createDirectClient(
|
|
1012
1020
|
e,
|
|
1013
1021
|
n,
|
|
1014
|
-
(
|
|
1022
|
+
(o) => this.handleInternalStateChange(o)
|
|
1015
1023
|
);
|
|
1016
1024
|
}
|
|
1017
1025
|
// ============================================================================
|
|
@@ -1269,64 +1277,67 @@ class ze {
|
|
|
1269
1277
|
throw new Error("directClient did not return a DirectState");
|
|
1270
1278
|
}
|
|
1271
1279
|
}
|
|
1280
|
+
const Te = "production";
|
|
1272
1281
|
export {
|
|
1273
|
-
|
|
1282
|
+
ve as AUTH_EXT_NOT_INITIALIZED,
|
|
1274
1283
|
j as BACKEND_SERVER_NOT_CONNECTED,
|
|
1275
1284
|
x as BACKEND_SERVER_NOT_REACHABLE,
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1285
|
+
_e as BROWSER_CONFIGS,
|
|
1286
|
+
Ke as BaseFacadeClient,
|
|
1287
|
+
$ as BodhiClientUserPrefsManager,
|
|
1288
|
+
Te as CORE_BUILD_MODE,
|
|
1279
1289
|
y as DIRECT_STATE_NOT_INITIALIZED,
|
|
1280
|
-
|
|
1290
|
+
ze as DirectClientBase,
|
|
1281
1291
|
F as EXTENSION_STATE_NOT_FOUND,
|
|
1282
1292
|
U as EXTENSION_STATE_NOT_INITIALIZED,
|
|
1283
1293
|
H as Logger,
|
|
1284
1294
|
z as NOOP_STATE_CALLBACK,
|
|
1285
|
-
|
|
1286
|
-
|
|
1295
|
+
je as OS_CONFIGS,
|
|
1296
|
+
Ne as OnboardingModal,
|
|
1287
1297
|
_ as PENDING_EXTENSION_READY,
|
|
1288
1298
|
m as SERVER_ERROR_CODES,
|
|
1289
|
-
|
|
1299
|
+
Ce as STORAGE_PREFIXES,
|
|
1290
1300
|
M as backendServerNotReady,
|
|
1291
1301
|
T as base64UrlEncode,
|
|
1292
1302
|
Q as buildError,
|
|
1293
1303
|
V as buildEvent,
|
|
1294
1304
|
K as buildResponse,
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1305
|
+
ie as createApiError,
|
|
1306
|
+
le as createDirectStateNotReachable,
|
|
1307
|
+
ce as createDirectStateNotReady,
|
|
1308
|
+
oe as createDirectStateReady,
|
|
1309
|
+
fe as createExtensionStateNotFound,
|
|
1310
|
+
de as createExtensionStateNotInitialized,
|
|
1311
|
+
J as createOAuthEndpoints,
|
|
1302
1312
|
v as createOperationError,
|
|
1303
1313
|
q as createStorageKeys,
|
|
1304
|
-
|
|
1305
|
-
ke as
|
|
1314
|
+
W as createStoragePrefixWithBasePath,
|
|
1315
|
+
ke as detectBrowser,
|
|
1316
|
+
Ee as detectOS,
|
|
1306
1317
|
E as extractUserInfo,
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1318
|
+
Ie as generateCodeChallenge,
|
|
1319
|
+
Ae as generateCodeVerifier,
|
|
1320
|
+
he as getBackendServerState,
|
|
1321
|
+
me as getExtensionId,
|
|
1322
|
+
ge as getServerUrl,
|
|
1323
|
+
we as handleRequest,
|
|
1324
|
+
ae as isApiResultError,
|
|
1314
1325
|
L as isApiResultOperationError,
|
|
1315
1326
|
P as isApiResultSuccess,
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1327
|
+
ye as isAuthError,
|
|
1328
|
+
xe as isAuthLoggedIn,
|
|
1329
|
+
be as isAuthLoggedOut,
|
|
1330
|
+
pe as isClientReady,
|
|
1320
1331
|
D as isDirectClientReady,
|
|
1321
|
-
|
|
1332
|
+
se as isDirectServerReady,
|
|
1322
1333
|
I as isDirectState,
|
|
1323
1334
|
B as isExtensionClientReady,
|
|
1324
1335
|
ue as isExtensionServerReady,
|
|
1325
1336
|
w as isExtensionState,
|
|
1326
|
-
|
|
1337
|
+
re as isOperationError,
|
|
1327
1338
|
A as isServerReady,
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1339
|
+
Se as isWebUIClient,
|
|
1340
|
+
Z as parseJwt,
|
|
1341
|
+
ee as refreshAccessToken,
|
|
1342
|
+
te as testServerConnectivity
|
|
1332
1343
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BUILD_MODE: string;
|
|
@@ -20,7 +20,7 @@ export declare abstract class BaseFacadeClient<TConfig, TExtClient extends IConn
|
|
|
20
20
|
protected authClientId: string;
|
|
21
21
|
protected config: TConfig;
|
|
22
22
|
protected onStateChange: StateChangeCallback;
|
|
23
|
-
constructor(authClientId: string, config: TConfig, onStateChange?: StateChangeCallback, storagePrefix?: string);
|
|
23
|
+
constructor(authClientId: string, config: TConfig, onStateChange?: StateChangeCallback, storagePrefix?: string, basePath?: string);
|
|
24
24
|
/**
|
|
25
25
|
* Create logger instance
|
|
26
26
|
* Subclasses extract logLevel from their specific config type
|
|
@@ -27,6 +27,18 @@ export declare const STORAGE_PREFIXES: {
|
|
|
27
27
|
readonly WEB: "bodhi:web";
|
|
28
28
|
readonly EXT: "bodhi:ext";
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Create storage prefix with basePath for path isolation
|
|
32
|
+
*
|
|
33
|
+
* @param basePath - Base path of app (e.g., '/', '/app1/')
|
|
34
|
+
* @param prefix - Storage prefix (e.g., 'bodhi:web', 'bodhijs:')
|
|
35
|
+
* @returns Combined prefix with basePath isolation
|
|
36
|
+
*
|
|
37
|
+
* Examples:
|
|
38
|
+
* - createStoragePrefixWithBasePath('/', 'bodhi:web') => '/:bodhi:web'
|
|
39
|
+
* - createStoragePrefixWithBasePath('/app1/', 'bodhi:web') => '/app1/:bodhi:web'
|
|
40
|
+
*/
|
|
41
|
+
export declare function createStoragePrefixWithBasePath(basePath: string, prefix: string): string;
|
|
30
42
|
/**
|
|
31
43
|
* User Preferences Storage Manager
|
|
32
44
|
*
|