@bodhiapp/bodhi-js-react 0.0.4 → 0.0.5

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.
Files changed (27) hide show
  1. package/dist/bodhi-browser-ext/src/types/bodhiext.d.ts +0 -1
  2. package/dist/bodhi-browser-ext/src/types/protocol.d.ts +0 -1
  3. package/dist/bodhi-js-sdk/core/src/errors.d.ts +0 -1
  4. package/dist/bodhi-js-sdk/core/src/facade-client-base.d.ts +0 -1
  5. package/dist/bodhi-js-sdk/core/src/interface.d.ts +0 -1
  6. package/dist/bodhi-js-sdk/core/src/logger.d.ts +0 -1
  7. package/dist/bodhi-js-sdk/core/src/oauth.d.ts +0 -1
  8. package/dist/bodhi-js-sdk/core/src/onboarding/config.d.ts +0 -1
  9. package/dist/bodhi-js-sdk/core/src/onboarding/modal.d.ts +0 -1
  10. package/dist/bodhi-js-sdk/core/src/onboarding/protocol-utils.d.ts +0 -1
  11. package/dist/bodhi-js-sdk/core/src/platform.d.ts +0 -1
  12. package/dist/bodhi-js-sdk/core/src/types/api.d.ts +0 -1
  13. package/dist/bodhi-js-sdk/core/src/types/callback.d.ts +0 -1
  14. package/dist/bodhi-js-sdk/core/src/types/client-state.d.ts +0 -1
  15. package/dist/bodhi-js-sdk/core/src/types/config.d.ts +0 -1
  16. package/dist/bodhi-js-sdk/core/src/types/platform.d.ts +0 -1
  17. package/dist/bodhi-js-sdk/react/src/BodhiProvider.d.ts +0 -1
  18. package/dist/bodhi-js-sdk/react/src/SetupModalProcessor.d.ts +0 -1
  19. package/dist/bodhi-js-sdk/react/src/client-ctx.d.ts +0 -1
  20. package/dist/bodhi-react.cjs.js +2 -2
  21. package/dist/bodhi-react.esm.d.ts +1 -0
  22. package/dist/bodhi-react.esm.js +133 -142
  23. package/dist/setup-modal/src/types/message-types.d.ts +0 -1
  24. package/dist/setup-modal/src/types/protocol.d.ts +0 -1
  25. package/dist/setup-modal/src/types/state.d.ts +0 -1
  26. package/dist/setup-modal/src/types/type-guards.d.ts +0 -1
  27. package/package.json +6 -5
@@ -1,5 +1,4 @@
1
1
  import { OpenAiApiError, PingResponse, CreateChatCompletionRequest, CreateChatCompletionResponse, CreateChatCompletionStreamResponse } from '@bodhiapp/ts-client';
2
-
3
2
  /**
4
3
  * HTTP response wrapper - body can be success type OR error type
5
4
  * Use isApiErrorResponse() to narrow the type based on status
@@ -1,6 +1,5 @@
1
1
  import { OpenAiApiError, ErrorBody } from '@bodhiapp/ts-client';
2
2
  import { ApiResponse, ServerStateInfo } from './bodhiext';
3
-
4
3
  /**
5
4
  * Validate OpenAI API error body structure
6
5
  * { error: { message: string, type: string } }
@@ -1,6 +1,5 @@
1
1
  import { ApiError, OperationError } from '../../../bodhi-browser-ext/src/types';
2
2
  import { OpenAiApiError } from '@bodhiapp/ts-client';
3
-
4
3
  /**
5
4
  * Create API error (HTTP 4xx/5xx from server)
6
5
  * Thrown for streaming responses when server returns error
@@ -3,7 +3,6 @@ import { IConnectionClient } from './interface';
3
3
  import { Logger } from './logger';
4
4
  import { BodhiClientUserPrefsManager } from './storage';
5
5
  import { ApiResponseResult, AuthLoggedIn, AuthLoggedOut, AuthState, BackendServerState, ClientState, ConnectionMode, DirectState, ExtensionState, InitParams, SerializedClientState, SerializedDirectState, SerializedExtensionState, StateChange, StateChangeCallback } from './types';
6
-
7
6
  /**
8
7
  * Base facade client with common delegation logic
9
8
  *
@@ -1,6 +1,5 @@
1
1
  import { CreateChatCompletionStreamResponse } from '@bodhiapp/ts-client';
2
2
  import { ApiResponseResult, AuthLoggedIn, AuthLoggedOut, AuthState, BackendServerState, ClientState, ConnectionMode, DirectState, ExtensionState, InitParams, StateChangeCallback } from './types';
3
-
4
3
  /**
5
4
  * ConnectionClient - Base interface for all client implementations
6
5
  *
@@ -1,5 +1,4 @@
1
1
  import { LogLevel } from './types/config';
2
-
3
2
  export declare class Logger {
4
3
  private prefix;
5
4
  private level;
@@ -1,5 +1,4 @@
1
1
  import { UserInfo } from './types';
2
-
3
2
  /**
4
3
  * Base64 URL encode a buffer (for PKCE)
5
4
  */
@@ -1,5 +1,4 @@
1
1
  import { Browser, OS } from '../../../../setup-modal/src/types';
2
-
3
2
  /**
4
3
  * Browser configurations with extension store URLs
5
4
  */
@@ -1,5 +1,4 @@
1
1
  import { MessageType, RequestMessage, ResponsePayload } from '../../../../setup-modal/src/types';
2
-
3
2
  import type * as ModalTypes from '@bodhiapp/setup-modal/types';
4
3
  /**
5
4
  * Async handler for modal requests
@@ -1,5 +1,4 @@
1
1
  import { MessageType, RequestPayload, ResponsePayload, RequestMessage, RequestId } from '../../../../setup-modal/src/types';
2
-
3
2
  /** Build fire-and-forget event message */
4
3
  export declare function buildEvent<T extends MessageType>(type: T, payload: RequestPayload<T>): {
5
4
  kind: "event";
@@ -1,5 +1,4 @@
1
1
  import { BrowserInfo, OSInfo } from './types';
2
-
3
2
  /**
4
3
  * Detects the current browser using UAParser.js
5
4
  */
@@ -1,6 +1,5 @@
1
1
  import { ApiResponse, OperationErrorResponse } from '../../../../bodhi-browser-ext/src/types';
2
2
  import { OpenAiApiError } from '@bodhiapp/ts-client';
3
-
4
3
  /**
5
4
  * Public API result type - discriminated union without protocol fields
6
5
  *
@@ -1,6 +1,5 @@
1
1
  import { ClientState } from './client-state';
2
2
  import { AuthState } from './user-info';
3
-
4
3
  /**
5
4
  * Discriminated union for state changes.
6
5
  * Allows single callback to handle both client state and auth state changes.
@@ -1,5 +1,4 @@
1
1
  import { OperationErrorResponse } from '../../../../bodhi-browser-ext/src/types';
2
-
3
2
  /**
4
3
  * Serialized direct client state for persistence
5
4
  * Stores minimal state needed to restore direct connection
@@ -1,5 +1,4 @@
1
1
  import { UserScope } from './user-info';
2
-
3
2
  /**
4
3
  * Log levels for client logging
5
4
  */
@@ -1,5 +1,4 @@
1
1
  import { BrowserType, OSType } from '../../../../setup-modal/src/types';
2
-
3
2
  /**
4
3
  * Browser detection result
5
4
  */
@@ -1,7 +1,6 @@
1
1
  import { AuthState, LogLevel, UIClient } from '../../core/src/index.ts';
2
2
  import { ReactNode } from 'react';
3
3
  import { ClientContextState } from './client-ctx';
4
-
5
4
  export type SetupState = 'ready' | 'loading' | 'loaded';
6
5
  export interface BodhiProviderProps {
7
6
  children: ReactNode;
@@ -1,6 +1,5 @@
1
1
  import { UIClient, LogLevel } from '../../core/src/index.ts';
2
2
  import { SetupState } from './BodhiProvider';
3
-
4
3
  interface SetupModalProcessorProps {
5
4
  client: UIClient;
6
5
  modalHtmlPath?: string;
@@ -1,5 +1,4 @@
1
1
  import { ClientState } from '../../core/src/index.ts';
2
-
3
2
  export interface ClientContextNotInitialized {
4
3
  type: 'not-initialized';
5
4
  }
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const B=require("react/jsx-runtime"),s=require("@bodhiapp/bodhi-js-core"),n=require("react"),m={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"};function H({client:e,modalHtmlPath:i,hideSetup:v,onSetupReady:C,setupState:D,basePath:O="/",logLevel:_="warn"}){const L=D!=="ready",E=n.useMemo(()=>new s.Logger("SetupModalProcessor",_),[_]),c=n.useRef(null),l=n.useMemo(()=>new s.BodhiClientUserPrefsManager(s.createStoragePrefixWithBasePath(O,"bodhijs:")),[O]),S=n.useRef(null),g=n.useCallback(t=>t==="direct"?"lna":t==="extension"?"extension":null,[]),R=n.useCallback(t=>t.extension==="ready"?{status:"ready",version:"unknown",id:t.extensionId}:t.extension==="not-found"?{status:"not-installed",error:{message:"Extension not found",code:"ext-not-installed"}}:{status:"unreachable",error:{message:"Client not initialized",code:"ext-connection-failed"}},[]),p=n.useCallback(t=>{if(t.server.status==="pending-extension-ready")return{status:"pending-extension-ready",error:{message:"Extension not ready",code:"server-pending-ext-ready"}};const r=t.server;switch(r.status){case"ready":return{status:"ready",version:r.version};case"setup":return{status:"setup",version:r.version,error:{message:r.error.message,code:"server-in-setup-status"}};case"resource-admin":return{status:"resource-admin",version:r.version,error:{message:r.error.message,code:"server-in-admin-status"}};case"error":return{status:"error",error:{message:r.error.message,code:"server-unexpected-error"}};case"not-reachable":return{status:"unreachable",error:{message:r.error.message,code:"server-conn-refused"}}}},[]),h=n.useCallback(t=>{if(t.server.status==="not-connected")return{status:"pending-lna-ready"};const r=t.server;switch(r.status){case"ready":return{status:"ready",version:r.version};case"setup":return{status:"setup",version:r.version};case"resource-admin":return{status:"resource-admin",version:r.version};case"error":case"not-reachable":return{status:"error",error:{message:r.error.message}}}},[]),x=n.useCallback((t,r)=>{if(t.server.status!=="pending-extension-ready"){const o=t.server.status;if(o==="ready"||o==="setup"||o==="resource-admin")return!0}if(r.server.status!=="not-connected"){const o=r.server.status;if(o==="ready"||o==="setup"||o==="resource-admin")return!0}return!1},[]),M=n.useCallback((t,r,o)=>{if(r==="skipped")return{status:"skipped",serverUrl:o};if(t.server.status!=="not-connected"){const a=t.server;return a.status==="ready"||a.status==="setup"||a.status==="resource-admin"?{status:"granted",serverUrl:o}:{status:"unreachable",serverUrl:o,error:{message:a.error.message,code:"lna-unreachable"}}}return r==="granted"?{status:"granted",serverUrl:o}:{status:"prompt",serverUrl:o}},[]),d=n.useCallback(async(t=!1)=>{const r=s.detectBrowser().type,o=s.detectOS().type;let a=await e.getExtensionState();(a.extension==="not-initialized"||t)&&(a=await e.testExtensionConnectivity());let u=await e.getDirectState();const y=l.getDirectStatus();y==="granted"&&(u.server.status==="not-connected"||t)&&(u=await e.testDirectConnectivity());const A=s.getServerUrl(u)||"http://localhost:1135",U=M(u,y,A);return e.getConnectionMode()===null&&(s.isDirectServerReady(u)?await e.setConnectionMode("direct"):s.isExtensionServerReady(a)&&await e.setConnectionMode("extension")),l.isServerInstallConfirmed()||x(a,u)&&l.setServerInstallConfirmed(!0),{extension:R(a),server:p(a),lna:U,lnaServer:h(u),env:{browser:r,os:o},browsers:s.BROWSER_CONFIGS,os:s.OS_CONFIGS,userConfirmations:{serverInstall:l.isServerInstallConfirmed()},selectedConnection:g(e.getConnectionMode())}},[e,l,R,p,h,g,M,x]),f=n.useCallback(()=>{if(!S.current)throw new Error("Cannot get state: currentStateRef is null");return{...S.current,userConfirmations:{serverInstall:l.isServerInstallConfirmed()},selectedConnection:g(e.getConnectionMode())}},[l,e,g]),w=n.useMemo(()=>({[m.MODAL_READY]:async()=>(E.info("MODAL_READY: building initial state"),{setupState:f()}),[m.MODAL_REFRESH]:async()=>{var o;E.info("MODAL_REFRESH: refreshing state");const t=await d(!0);S.current=t;const r=f();return E.info(`MODAL_REFRESH: state refreshed
2
- `,JSON.stringify(r,null,2)),(o=c.current)==null||o.updateState(f()),{setupState:r}},[m.MODAL_LNA_CONNECT]:async t=>{var u,y;const r=t.payload.serverUrl;console.log("[SetupModalProcessor] LNA connect:",r);const o=await e.testDirectConnectivity(r);if(o.server.status!=="not-connected"){const b=o.server.status;if(b==="ready"||b==="setup"||b==="resource-admin"){l.setDirectStatus("granted"),e.getConnectionMode()===null&&await e.setConnectionMode("direct");const A=await d();return S.current=A,(u=c.current)==null||u.updateState(f()),{success:!0}}}const a=await d();return S.current=a,(y=c.current)==null||y.updateState(f()),{success:!1}},[m.MODAL_LNA_SKIP]:async()=>{var r;l.setDirectStatus("skipped");const t=await d();return S.current=t,(r=c.current)==null||r.updateState(f()),{success:!0}},[m.MODAL_CLOSE]:()=>{v()},[m.MODAL_COMPLETE]:()=>{v()},[m.MODAL_CONFIRM_SERVER_INSTALL]:t=>{var r;return l.setServerInstallConfirmed(t.payload.confirmed),(r=c.current)==null||r.updateState(f()),{success:!0}},[m.MODAL_SELECT_CONNECTION]:async t=>{var a;const o=t.payload.connection==="lna"?"direct":"extension";return await e.setConnectionMode(o),(a=c.current)==null||a.updateState(f()),{success:!0}}}),[E,e,l,d,f,h,v]);return n.useEffect(()=>(c.current=new s.OnboardingModal({modalHtmlPath:i,handlers:w}),()=>{var t;(t=c.current)==null||t.destroy(),c.current=null}),[i,w]),n.useEffect(()=>{L&&c.current?d(!0).then(t=>{var r;S.current=t,(r=c.current)==null||r.show(t),C==null||C()}).catch(t=>{console.error("[SetupModalProcessor] buildSetupState failed:",t)}):!L&&c.current&&c.current.destroy()},[L,d,C]),null}const k=n.createContext(null);k.displayName="BodhiContext";function G({children:e,client:i,modalHtmlPath:v,handleCallback:C=!0,callbackPath:D="/callback",basePath:O="/",logLevel:_="warn"}){const L=n.useRef(!1),E=n.useRef(!1),[c,l]=n.useState({type:"not-initialized"}),[S,g]=n.useState(null),[R,p]=n.useState(!1),[h,x]=n.useState("ready");n.useEffect(()=>{const a=u=>{switch(u.type){case"client-state":l(u.state);break;case"auth-state":g(u.state),p(!1);break}};return i.setStateCallback(a),()=>{i.setStateCallback(s.NOOP_STATE_CALLBACK)}},[i]);const M=n.useCallback(async()=>{x("loading")},[]),d=n.useCallback(()=>{x("ready")},[]),f=n.useCallback(()=>{x("loaded")},[]),w=n.useCallback(async a=>{l({type:"initializing"});try{await i.init(a||{})}catch(u){console.error("[BodhiProvider] Init failed:",u)}},[i]);n.useEffect(()=>{if(E.current)return;E.current=!0,(async()=>{if(await w(),!C)return;const u=new URL(window.location.href);if(u.pathname!==D)return;const y=u.searchParams.get("code"),b=u.searchParams.get("state");!y||!b||L.current||(L.current=!0,s.isWebUIClient(i)&&(p(!0),i.handleOAuthCallback(y,b).then(()=>{window.history.replaceState({},"",O)}).catch(A=>{console.error("OAuth callback failed:",A),g({isLoggedIn:!1,error:{message:A instanceof Error?A.message:"OAuth callback failed",code:"OAUTH_CALLBACK_FAILED"}}),p(!1),window.history.replaceState({},"",O)})))})()},[w,i,C,D,O]);const t=n.useCallback(async()=>{p(!0);try{await i.login()}catch(a){g({isLoggedIn:!1,error:{message:a instanceof Error?a.message:"Login failed",code:"LOGIN_FAILED"}}),p(!1)}},[i]),r=n.useCallback(async()=>{try{await i.logout()}catch(a){g({isLoggedIn:!1,error:{message:a instanceof Error?a.message:"Logout failed",code:"LOGOUT_FAILED"}})}},[i]),o=n.useMemo(()=>({client:i,clientState:c,auth:S,authLoading:R,login:t,logout:r,showSetup:M,hideSetup:d,setupState:h}),[i,c,S,R,h,t,r,M,d]);return B.jsxs(k.Provider,{value:o,children:[B.jsx(H,{client:i,modalHtmlPath:v,hideSetup:d,onSetupReady:f,setupState:h,basePath:O,logLevel:_}),e]})}function K(){const e=n.useContext(k);if(!e)throw new Error("useBodhi must be used within BodhiProvider");return{client:e.client,clientState:e.clientState,setupState:e.setupState,auth:e.auth,authLoading:e.authLoading,login:e.login,logout:e.logout,showSetup:e.showSetup,hideSetup:e.hideSetup}}function N(e){return e.type==="not-initialized"}function P(e){return e.type==="initializing"}function I(e){return!(N(e)||P(e))}function T(e){return I(e)?s.isClientReady(e):!1}function z(e){if(N(e))return{ready:!1,actualState:"not-initialized",mode:null};if(P(e))return{ready:!1,actualState:"initializing",mode:null};const i=s.isExtensionState(e)?"extension":"direct",v=s.isClientReady(e),C=s.isExtensionState(e)?e.extension:e.server.status==="not-connected"?"not-connected":"ready";return{ready:v,actualState:C,mode:i}}function j(e){if(!I(e))return{ready:!1,actualState:"n/a"};const i=e.server;return{ready:i.status==="ready",actualState:i.status}}function F(e){return I(e)?s.isClientReady(e)&&e.server.status==="ready":!1}const V={isNotInitialized:N,isInitializing:P,isInitialized:I,isReady:T,getClientInitState:z,getServerState:j,isOverallReady:F},W="production";Object.defineProperty(exports,"createApiError",{enumerable:!0,get:()=>s.createApiError});Object.defineProperty(exports,"createOperationError",{enumerable:!0,get:()=>s.createOperationError});Object.defineProperty(exports,"isApiResultError",{enumerable:!0,get:()=>s.isApiResultError});Object.defineProperty(exports,"isApiResultOperationError",{enumerable:!0,get:()=>s.isApiResultOperationError});Object.defineProperty(exports,"isApiResultSuccess",{enumerable:!0,get:()=>s.isApiResultSuccess});Object.defineProperty(exports,"isAuthError",{enumerable:!0,get:()=>s.isAuthError});Object.defineProperty(exports,"isAuthLoggedIn",{enumerable:!0,get:()=>s.isAuthLoggedIn});Object.defineProperty(exports,"isClientReady",{enumerable:!0,get:()=>s.isClientReady});Object.defineProperty(exports,"isDirectState",{enumerable:!0,get:()=>s.isDirectState});Object.defineProperty(exports,"isExtensionState",{enumerable:!0,get:()=>s.isExtensionState});Object.defineProperty(exports,"isOperationError",{enumerable:!0,get:()=>s.isOperationError});exports.BodhiProvider=G;exports.BodhiReactContext=k;exports.ClientCtxState=V;exports.REACT_BUILD_MODE=W;exports.getClientInitState=z;exports.getServerState=j;exports.isClientCtxInitialized=I;exports.isClientCtxInitializing=P;exports.isClientCtxNotInitialized=N;exports.isClientCtxReady=T;exports.isOverallReady=F;exports.useBodhi=K;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const B=require("react/jsx-runtime"),s=require("@bodhiapp/bodhi-js-core"),n=require("react"),p={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"};function H({client:e,modalHtmlPath:o,hideSetup:y,onSetupReady:m,setupState:I,basePath:v="/",logLevel:D="warn"}){const b=I!=="ready",O=n.useMemo(()=>new s.Logger("SetupModalProcessor",D),[D]),c=n.useRef(null),l=n.useMemo(()=>new s.BodhiClientUserPrefsManager(s.createStoragePrefixWithBasePath(v,"bodhijs:")),[v]),S=n.useRef(null),C=n.useCallback(t=>t==="direct"?"lna":t==="extension"?"extension":null,[]),L=n.useCallback(t=>t.extension==="ready"?{status:"ready",version:"unknown",id:t.extensionId}:t.extension==="not-found"?{status:"not-installed",error:{message:"Extension not found",code:"ext-not-installed"}}:{status:"unreachable",error:{message:"Client not initialized",code:"ext-connection-failed"}},[]),g=n.useCallback(t=>{if(t.server.status==="pending-extension-ready")return{status:"pending-extension-ready",error:{message:"Extension not ready",code:"server-pending-ext-ready"}};const r=t.server;switch(r.status){case"ready":return{status:"ready",version:r.version};case"setup":return{status:"setup",version:r.version,error:{message:r.error.message,code:"server-in-setup-status"}};case"resource-admin":return{status:"resource-admin",version:r.version,error:{message:r.error.message,code:"server-in-admin-status"}};case"error":return{status:"error",error:{message:r.error.message,code:"server-unexpected-error"}};case"not-reachable":return{status:"unreachable",error:{message:r.error.message,code:"server-conn-refused"}}}},[]),E=n.useCallback(t=>{if(t.server.status==="not-connected")return{status:"pending-lna-ready"};const r=t.server;switch(r.status){case"ready":return{status:"ready",version:r.version};case"setup":return{status:"setup",version:r.version};case"resource-admin":return{status:"resource-admin",version:r.version};case"error":case"not-reachable":return{status:"error",error:{message:r.error.message}}}},[]),A=n.useCallback((t,r)=>{if(t.server.status!=="pending-extension-ready"){const i=t.server.status;if(i==="ready"||i==="setup"||i==="resource-admin")return!0}if(r.server.status!=="not-connected"){const i=r.server.status;if(i==="ready"||i==="setup"||i==="resource-admin")return!0}return!1},[]),R=n.useCallback((t,r,i)=>{if(r==="skipped")return{status:"skipped",serverUrl:i};if(t.server.status!=="not-connected"){const a=t.server;return a.status==="ready"||a.status==="setup"||a.status==="resource-admin"?{status:"granted",serverUrl:i}:{status:"unreachable",serverUrl:i,error:{message:a.error.message,code:"lna-unreachable"}}}return r==="granted"?{status:"granted",serverUrl:i}:{status:"prompt",serverUrl:i}},[]),d=n.useCallback(async(t=!1)=>{const r=s.detectBrowser().type,i=s.detectOS().type;let a=await e.getExtensionState();(a.extension==="not-initialized"||t)&&(a=await e.testExtensionConnectivity());let u=await e.getDirectState();const h=l.getDirectStatus();h==="granted"&&(u.server.status==="not-connected"||t)&&(u=await e.testDirectConnectivity());const M=s.getServerUrl(u)||"http://localhost:1135",U=R(u,h,M);return e.getConnectionMode()===null&&(s.isDirectServerReady(u)?await e.setConnectionMode("direct"):s.isExtensionServerReady(a)&&await e.setConnectionMode("extension")),l.isServerInstallConfirmed()||A(a,u)&&l.setServerInstallConfirmed(!0),{extension:L(a),server:g(a),lna:U,lnaServer:E(u),env:{browser:r,os:i},browsers:s.BROWSER_CONFIGS,os:s.OS_CONFIGS,userConfirmations:{serverInstall:l.isServerInstallConfirmed()},selectedConnection:C(e.getConnectionMode())}},[e,l,L,g,E,C,R,A]),f=n.useCallback(()=>{if(!S.current)throw new Error("Cannot get state: currentStateRef is null");return{...S.current,userConfirmations:{serverInstall:l.isServerInstallConfirmed()},selectedConnection:C(e.getConnectionMode())}},[l,e,C]),x=n.useMemo(()=>({[p.MODAL_READY]:async()=>(O.info("MODAL_READY: building initial state"),{setupState:f()}),[p.MODAL_REFRESH]:async()=>{O.info("MODAL_REFRESH: refreshing state");const t=await d(!0);S.current=t;const r=f();return O.info(`MODAL_REFRESH: state refreshed
2
+ `,JSON.stringify(r,null,2)),c.current?.updateState(f()),{setupState:r}},[p.MODAL_LNA_CONNECT]:async t=>{const r=t.payload.serverUrl;console.log("[SetupModalProcessor] LNA connect:",r);const i=await e.testDirectConnectivity(r);if(i.server.status!=="not-connected"){const u=i.server.status;if(u==="ready"||u==="setup"||u==="resource-admin"){l.setDirectStatus("granted"),e.getConnectionMode()===null&&await e.setConnectionMode("direct");const h=await d();return S.current=h,c.current?.updateState(f()),{success:!0}}}const a=await d();return S.current=a,c.current?.updateState(f()),{success:!1}},[p.MODAL_LNA_SKIP]:async()=>{l.setDirectStatus("skipped");const t=await d();return S.current=t,c.current?.updateState(f()),{success:!0}},[p.MODAL_CLOSE]:()=>{y()},[p.MODAL_COMPLETE]:()=>{y()},[p.MODAL_CONFIRM_SERVER_INSTALL]:t=>(l.setServerInstallConfirmed(t.payload.confirmed),c.current?.updateState(f()),{success:!0}),[p.MODAL_SELECT_CONNECTION]:async t=>{const i=t.payload.connection==="lna"?"direct":"extension";return await e.setConnectionMode(i),c.current?.updateState(f()),{success:!0}}}),[O,e,l,d,f,E,y]);return n.useEffect(()=>(c.current=new s.OnboardingModal({modalHtmlPath:o,handlers:x}),()=>{c.current?.destroy(),c.current=null}),[o,x]),n.useEffect(()=>{b&&c.current?d(!0).then(t=>{S.current=t,c.current?.show(t),m?.()}).catch(t=>{console.error("[SetupModalProcessor] buildSetupState failed:",t)}):!b&&c.current&&c.current.destroy()},[b,d,m]),null}const _=n.createContext(null);_.displayName="BodhiContext";function G({children:e,client:o,modalHtmlPath:y,handleCallback:m=!0,callbackPath:I="/callback",basePath:v="/",logLevel:D="warn"}){const b=n.useRef(!1),O=n.useRef(!1),[c,l]=n.useState({type:"not-initialized"}),[S,C]=n.useState(null),[L,g]=n.useState(!1),[E,A]=n.useState("ready");n.useEffect(()=>{const a=u=>{switch(u.type){case"client-state":l(u.state);break;case"auth-state":C(u.state),g(!1);break}};return o.setStateCallback(a),()=>{o.setStateCallback(s.NOOP_STATE_CALLBACK)}},[o]);const R=n.useCallback(async()=>{A("loading")},[]),d=n.useCallback(()=>{A("ready")},[]),f=n.useCallback(()=>{A("loaded")},[]),x=n.useCallback(async a=>{l({type:"initializing"});try{await o.init(a||{})}catch(u){console.error("[BodhiProvider] Init failed:",u)}},[o]);n.useEffect(()=>{if(O.current)return;O.current=!0,(async()=>{if(await x(),!m)return;const u=new URL(window.location.href);if(u.pathname!==I)return;const h=u.searchParams.get("code"),P=u.searchParams.get("state");!h||!P||b.current||(b.current=!0,s.isWebUIClient(o)&&(g(!0),o.handleOAuthCallback(h,P).then(()=>{window.history.replaceState({},"",v)}).catch(M=>{console.error("OAuth callback failed:",M),C({isLoggedIn:!1,error:{message:M instanceof Error?M.message:"OAuth callback failed",code:"OAUTH_CALLBACK_FAILED"}}),g(!1),window.history.replaceState({},"",v)})))})()},[x,o,m,I,v]);const t=n.useCallback(async()=>{g(!0);try{await o.login()}catch(a){C({isLoggedIn:!1,error:{message:a instanceof Error?a.message:"Login failed",code:"LOGIN_FAILED"}}),g(!1)}},[o]),r=n.useCallback(async()=>{try{await o.logout()}catch(a){C({isLoggedIn:!1,error:{message:a instanceof Error?a.message:"Logout failed",code:"LOGOUT_FAILED"}})}},[o]),i=n.useMemo(()=>({client:o,clientState:c,auth:S,authLoading:L,login:t,logout:r,showSetup:R,hideSetup:d,setupState:E}),[o,c,S,L,E,t,r,R,d]);return B.jsxs(_.Provider,{value:i,children:[B.jsx(H,{client:o,modalHtmlPath:y,hideSetup:d,onSetupReady:f,setupState:E,basePath:v,logLevel:D}),e]})}function K(){const e=n.useContext(_);if(!e)throw new Error("useBodhi must be used within BodhiProvider");return{client:e.client,clientState:e.clientState,setupState:e.setupState,auth:e.auth,authLoading:e.authLoading,login:e.login,logout:e.logout,showSetup:e.showSetup,hideSetup:e.hideSetup}}function k(e){return e.type==="not-initialized"}function N(e){return e.type==="initializing"}function w(e){return!(k(e)||N(e))}function T(e){return w(e)?s.isClientReady(e):!1}function z(e){if(k(e))return{ready:!1,actualState:"not-initialized",mode:null};if(N(e))return{ready:!1,actualState:"initializing",mode:null};const o=s.isExtensionState(e)?"extension":"direct",y=s.isClientReady(e),m=s.isExtensionState(e)?e.extension:e.server.status==="not-connected"?"not-connected":"ready";return{ready:y,actualState:m,mode:o}}function j(e){if(!w(e))return{ready:!1,actualState:"n/a"};const o=e.server;return{ready:o.status==="ready",actualState:o.status}}function F(e){return w(e)?s.isClientReady(e)&&e.server.status==="ready":!1}const V={isNotInitialized:k,isInitializing:N,isInitialized:w,isReady:T,getClientInitState:z,getServerState:j,isOverallReady:F},W="production";Object.defineProperty(exports,"createApiError",{enumerable:!0,get:()=>s.createApiError});Object.defineProperty(exports,"createOperationError",{enumerable:!0,get:()=>s.createOperationError});Object.defineProperty(exports,"isApiResultError",{enumerable:!0,get:()=>s.isApiResultError});Object.defineProperty(exports,"isApiResultOperationError",{enumerable:!0,get:()=>s.isApiResultOperationError});Object.defineProperty(exports,"isApiResultSuccess",{enumerable:!0,get:()=>s.isApiResultSuccess});Object.defineProperty(exports,"isAuthError",{enumerable:!0,get:()=>s.isAuthError});Object.defineProperty(exports,"isAuthLoggedIn",{enumerable:!0,get:()=>s.isAuthLoggedIn});Object.defineProperty(exports,"isClientReady",{enumerable:!0,get:()=>s.isClientReady});Object.defineProperty(exports,"isDirectState",{enumerable:!0,get:()=>s.isDirectState});Object.defineProperty(exports,"isExtensionState",{enumerable:!0,get:()=>s.isExtensionState});Object.defineProperty(exports,"isOperationError",{enumerable:!0,get:()=>s.isOperationError});exports.BodhiProvider=G;exports.BodhiReactContext=_;exports.ClientCtxState=V;exports.REACT_BUILD_MODE=W;exports.getClientInitState=z;exports.getServerState=j;exports.isClientCtxInitialized=w;exports.isClientCtxInitializing=N;exports.isClientCtxNotInitialized=k;exports.isClientCtxReady=T;exports.isOverallReady=F;exports.useBodhi=K;
@@ -1 +1,2 @@
1
1
  export * from './bodhi-js-sdk/react/src/index'
2
+ export {}
@@ -1,8 +1,8 @@
1
1
  import { jsxs as G, jsx as K } from "react/jsx-runtime";
2
2
  import { Logger as V, BodhiClientUserPrefsManager as W, createStoragePrefixWithBasePath as j, detectBrowser as Y, detectOS as J, getServerUrl as q, isDirectServerReady as Q, isExtensionServerReady as X, OS_CONFIGS as Z, BROWSER_CONFIGS as $, OnboardingModal as ee, NOOP_STATE_CALLBACK as te, isWebUIClient as re, isClientReady as B, isExtensionState as U } from "@bodhiapp/bodhi-js-core";
3
- import { createApiError as ye, createOperationError as he, isApiResultError as Le, isApiResultOperationError as Ee, isApiResultSuccess as Oe, isAuthError as Ae, isAuthLoggedIn as we, isClientReady as xe, isDirectState as Me, isExtensionState as _e, isOperationError as De } from "@bodhiapp/bodhi-js-core";
4
- import { useMemo as N, useRef as b, useCallback as c, useEffect as T, createContext as ne, useState as R, useContext as se } from "react";
5
- const m = {
3
+ import { createApiError as ve, createOperationError as he, isApiResultError as Le, isApiResultOperationError as Ee, isApiResultSuccess as Oe, isAuthError as Ae, isAuthLoggedIn as we, isClientReady as xe, isDirectState as Me, isExtensionState as _e, isOperationError as De } from "@bodhiapp/bodhi-js-core";
4
+ import { useMemo as I, useRef as N, useCallback as c, useEffect as b, createContext as ne, useState as R, useContext as se } from "react";
5
+ const p = {
6
6
  // Modal lifecycle
7
7
  MODAL_READY: "modal:ready",
8
8
  MODAL_REFRESH: "modal:refresh",
@@ -18,20 +18,20 @@ const m = {
18
18
  };
19
19
  function ae({
20
20
  client: e,
21
- modalHtmlPath: a,
22
- hideSetup: v,
23
- onSetupReady: S,
24
- setupState: D,
21
+ modalHtmlPath: s,
22
+ hideSetup: C,
23
+ onSetupReady: m,
24
+ setupState: _,
25
25
  basePath: y = "/",
26
- logLevel: I = "warn"
26
+ logLevel: D = "warn"
27
27
  }) {
28
- const A = D !== "ready", h = N(() => new V("SetupModalProcessor", I), [I]), i = b(null), u = N(
28
+ const E = _ !== "ready", v = I(() => new V("SetupModalProcessor", D), [D]), i = N(null), u = I(
29
29
  () => new W(j(y, "bodhijs:")),
30
30
  [y]
31
- ), f = b(null), g = c(
31
+ ), f = N(null), S = c(
32
32
  (t) => t === "direct" ? "lna" : t === "extension" ? "extension" : null,
33
33
  []
34
- ), x = c((t) => t.extension === "ready" ? {
34
+ ), A = c((t) => t.extension === "ready" ? {
35
35
  status: "ready",
36
36
  version: "unknown",
37
37
  // TODO: have ExtensionState also get extension version
@@ -42,7 +42,7 @@ function ae({
42
42
  } : {
43
43
  status: "unreachable",
44
44
  error: { message: "Client not initialized", code: "ext-connection-failed" }
45
- }, []), p = c((t) => {
45
+ }, []), g = c((t) => {
46
46
  if (t.server.status === "pending-extension-ready")
47
47
  return {
48
48
  status: "pending-extension-ready",
@@ -75,7 +75,7 @@ function ae({
75
75
  error: { message: r.error.message, code: "server-conn-refused" }
76
76
  };
77
77
  }
78
- }, []), L = c((t) => {
78
+ }, []), h = c((t) => {
79
79
  if (t.server.status === "not-connected")
80
80
  return { status: "pending-lna-ready" };
81
81
  const r = t.server;
@@ -90,66 +90,66 @@ function ae({
90
90
  case "not-reachable":
91
91
  return { status: "error", error: { message: r.error.message } };
92
92
  }
93
- }, []), w = c(
93
+ }, []), O = c(
94
94
  (t, r) => {
95
95
  if (t.server.status !== "pending-extension-ready") {
96
- const s = t.server.status;
97
- if (s === "ready" || s === "setup" || s === "resource-admin")
96
+ const a = t.server.status;
97
+ if (a === "ready" || a === "setup" || a === "resource-admin")
98
98
  return !0;
99
99
  }
100
100
  if (r.server.status !== "not-connected") {
101
- const s = r.server.status;
102
- if (s === "ready" || s === "setup" || s === "resource-admin")
101
+ const a = r.server.status;
102
+ if (a === "ready" || a === "setup" || a === "resource-admin")
103
103
  return !0;
104
104
  }
105
105
  return !1;
106
106
  },
107
107
  []
108
- ), M = c(
109
- (t, r, s) => {
108
+ ), w = c(
109
+ (t, r, a) => {
110
110
  if (r === "skipped")
111
- return { status: "skipped", serverUrl: s };
111
+ return { status: "skipped", serverUrl: a };
112
112
  if (t.server.status !== "not-connected") {
113
113
  const n = t.server;
114
- return n.status === "ready" || n.status === "setup" || n.status === "resource-admin" ? { status: "granted", serverUrl: s } : {
114
+ return n.status === "ready" || n.status === "setup" || n.status === "resource-admin" ? { status: "granted", serverUrl: a } : {
115
115
  status: "unreachable",
116
- serverUrl: s,
116
+ serverUrl: a,
117
117
  error: { message: n.error.message, code: "lna-unreachable" }
118
118
  };
119
119
  }
120
- return r === "granted" ? { status: "granted", serverUrl: s } : { status: "prompt", serverUrl: s };
120
+ return r === "granted" ? { status: "granted", serverUrl: a } : { status: "prompt", serverUrl: a };
121
121
  },
122
122
  []
123
123
  ), d = c(
124
124
  async (t = !1) => {
125
- const r = Y().type, s = J().type;
125
+ const r = Y().type, a = J().type;
126
126
  let n = await e.getExtensionState();
127
127
  (n.extension === "not-initialized" || t) && (n = await e.testExtensionConnectivity());
128
128
  let o = await e.getDirectState();
129
- const C = u.getDirectStatus();
130
- C === "granted" && (o.server.status === "not-connected" || t) && (o = await e.testDirectConnectivity());
131
- const O = q(o) || "http://localhost:1135", H = M(o, C, O);
132
- return e.getConnectionMode() === null && (Q(o) ? await e.setConnectionMode("direct") : X(n) && await e.setConnectionMode("extension")), u.isServerInstallConfirmed() || w(n, o) && u.setServerInstallConfirmed(!0), {
133
- extension: x(n),
134
- server: p(n),
129
+ const L = u.getDirectStatus();
130
+ L === "granted" && (o.server.status === "not-connected" || t) && (o = await e.testDirectConnectivity());
131
+ const M = q(o) || "http://localhost:1135", H = w(o, L, M);
132
+ return e.getConnectionMode() === null && (Q(o) ? await e.setConnectionMode("direct") : X(n) && await e.setConnectionMode("extension")), u.isServerInstallConfirmed() || O(n, o) && u.setServerInstallConfirmed(!0), {
133
+ extension: A(n),
134
+ server: g(n),
135
135
  lna: H,
136
- lnaServer: L(o),
137
- env: { browser: r, os: s },
136
+ lnaServer: h(o),
137
+ env: { browser: r, os: a },
138
138
  browsers: $,
139
139
  os: Z,
140
140
  userConfirmations: { serverInstall: u.isServerInstallConfirmed() },
141
- selectedConnection: g(e.getConnectionMode())
141
+ selectedConnection: S(e.getConnectionMode())
142
142
  };
143
143
  },
144
144
  [
145
145
  e,
146
146
  u,
147
- x,
148
- p,
149
- L,
147
+ A,
150
148
  g,
151
- M,
152
- w
149
+ h,
150
+ S,
151
+ w,
152
+ O
153
153
  ]
154
154
  ), l = c(() => {
155
155
  if (!f.current)
@@ -161,157 +161,148 @@ function ae({
161
161
  serverInstall: u.isServerInstallConfirmed()
162
162
  },
163
163
  // Override selectedConnection from client (in case changed via handler)
164
- selectedConnection: g(e.getConnectionMode())
164
+ selectedConnection: S(e.getConnectionMode())
165
165
  };
166
- }, [u, e, g]), _ = N(
166
+ }, [u, e, S]), x = I(
167
167
  () => ({
168
- [m.MODAL_READY]: async () => (h.info("MODAL_READY: building initial state"), { setupState: l() }),
169
- [m.MODAL_REFRESH]: async () => {
170
- var s;
171
- h.info("MODAL_REFRESH: refreshing state");
168
+ [p.MODAL_READY]: async () => (v.info("MODAL_READY: building initial state"), { setupState: l() }),
169
+ [p.MODAL_REFRESH]: async () => {
170
+ v.info("MODAL_REFRESH: refreshing state");
172
171
  const t = await d(!0);
173
172
  f.current = t;
174
173
  const r = l();
175
- return h.info(`MODAL_REFRESH: state refreshed
176
- `, JSON.stringify(r, null, 2)), (s = i.current) == null || s.updateState(l()), { setupState: r };
174
+ return v.info(`MODAL_REFRESH: state refreshed
175
+ `, JSON.stringify(r, null, 2)), i.current?.updateState(l()), { setupState: r };
177
176
  },
178
- [m.MODAL_LNA_CONNECT]: async (t) => {
179
- var o, C;
177
+ [p.MODAL_LNA_CONNECT]: async (t) => {
180
178
  const r = t.payload.serverUrl;
181
179
  console.log("[SetupModalProcessor] LNA connect:", r);
182
- const s = await e.testDirectConnectivity(r);
183
- if (s.server.status !== "not-connected") {
184
- const E = s.server.status;
185
- if (E === "ready" || E === "setup" || E === "resource-admin") {
180
+ const a = await e.testDirectConnectivity(r);
181
+ if (a.server.status !== "not-connected") {
182
+ const o = a.server.status;
183
+ if (o === "ready" || o === "setup" || o === "resource-admin") {
186
184
  u.setDirectStatus("granted"), e.getConnectionMode() === null && await e.setConnectionMode("direct");
187
- const O = await d();
188
- return f.current = O, (o = i.current) == null || o.updateState(l()), { success: !0 };
185
+ const L = await d();
186
+ return f.current = L, i.current?.updateState(l()), { success: !0 };
189
187
  }
190
188
  }
191
189
  const n = await d();
192
- return f.current = n, (C = i.current) == null || C.updateState(l()), { success: !1 };
190
+ return f.current = n, i.current?.updateState(l()), { success: !1 };
193
191
  },
194
- [m.MODAL_LNA_SKIP]: async () => {
195
- var r;
192
+ [p.MODAL_LNA_SKIP]: async () => {
196
193
  u.setDirectStatus("skipped");
197
194
  const t = await d();
198
- return f.current = t, (r = i.current) == null || r.updateState(l()), { success: !0 };
195
+ return f.current = t, i.current?.updateState(l()), { success: !0 };
199
196
  },
200
- [m.MODAL_CLOSE]: () => {
201
- v();
197
+ [p.MODAL_CLOSE]: () => {
198
+ C();
202
199
  },
203
- [m.MODAL_COMPLETE]: () => {
204
- v();
200
+ [p.MODAL_COMPLETE]: () => {
201
+ C();
205
202
  },
206
- [m.MODAL_CONFIRM_SERVER_INSTALL]: (t) => {
207
- var r;
208
- return u.setServerInstallConfirmed(t.payload.confirmed), (r = i.current) == null || r.updateState(l()), { success: !0 };
209
- },
210
- [m.MODAL_SELECT_CONNECTION]: async (t) => {
211
- var n;
212
- const s = t.payload.connection === "lna" ? "direct" : "extension";
213
- return await e.setConnectionMode(s), (n = i.current) == null || n.updateState(l()), { success: !0 };
203
+ [p.MODAL_CONFIRM_SERVER_INSTALL]: (t) => (u.setServerInstallConfirmed(t.payload.confirmed), i.current?.updateState(l()), { success: !0 }),
204
+ [p.MODAL_SELECT_CONNECTION]: async (t) => {
205
+ const a = t.payload.connection === "lna" ? "direct" : "extension";
206
+ return await e.setConnectionMode(a), i.current?.updateState(l()), { success: !0 };
214
207
  }
215
208
  }),
216
- [h, e, u, d, l, L, v]
209
+ [v, e, u, d, l, h, C]
217
210
  );
218
- return T(() => (i.current = new ee({ modalHtmlPath: a, handlers: _ }), () => {
219
- var t;
220
- (t = i.current) == null || t.destroy(), i.current = null;
221
- }), [a, _]), T(() => {
222
- A && i.current ? d(!0).then((t) => {
223
- var r;
224
- f.current = t, (r = i.current) == null || r.show(t), S == null || S();
211
+ return b(() => (i.current = new ee({ modalHtmlPath: s, handlers: x }), () => {
212
+ i.current?.destroy(), i.current = null;
213
+ }), [s, x]), b(() => {
214
+ E && i.current ? d(!0).then((t) => {
215
+ f.current = t, i.current?.show(t), m?.();
225
216
  }).catch((t) => {
226
217
  console.error("[SetupModalProcessor] buildSetupState failed:", t);
227
- }) : !A && i.current && i.current.destroy();
228
- }, [A, d, S]), null;
218
+ }) : !E && i.current && i.current.destroy();
219
+ }, [E, d, m]), null;
229
220
  }
230
221
  const z = ne(null);
231
222
  z.displayName = "BodhiContext";
232
223
  function Se({
233
224
  children: e,
234
- client: a,
235
- modalHtmlPath: v,
236
- handleCallback: S = !0,
237
- callbackPath: D = "/callback",
225
+ client: s,
226
+ modalHtmlPath: C,
227
+ handleCallback: m = !0,
228
+ callbackPath: _ = "/callback",
238
229
  basePath: y = "/",
239
- logLevel: I = "warn"
230
+ logLevel: D = "warn"
240
231
  }) {
241
- const A = b(!1), h = b(!1), [i, u] = R(
232
+ const E = N(!1), v = N(!1), [i, u] = R(
242
233
  { type: "not-initialized" }
243
234
  // Start with UI state, client.init() will update
244
- ), [f, g] = R(null), [x, p] = R(!1), [L, w] = R("ready");
245
- T(() => {
235
+ ), [f, S] = R(null), [A, g] = R(!1), [h, O] = R("ready");
236
+ b(() => {
246
237
  const n = (o) => {
247
238
  switch (o.type) {
248
239
  case "client-state":
249
240
  u(o.state);
250
241
  break;
251
242
  case "auth-state":
252
- g(o.state), p(!1);
243
+ S(o.state), g(!1);
253
244
  break;
254
245
  }
255
246
  };
256
- return a.setStateCallback(n), () => {
257
- a.setStateCallback(te);
247
+ return s.setStateCallback(n), () => {
248
+ s.setStateCallback(te);
258
249
  };
259
- }, [a]);
260
- const M = c(async () => {
261
- w("loading");
250
+ }, [s]);
251
+ const w = c(async () => {
252
+ O("loading");
262
253
  }, []), d = c(() => {
263
- w("ready");
254
+ O("ready");
264
255
  }, []), l = c(() => {
265
- w("loaded");
266
- }, []), _ = c(
256
+ O("loaded");
257
+ }, []), x = c(
267
258
  async (n) => {
268
259
  u({ type: "initializing" });
269
260
  try {
270
- await a.init(n || {});
261
+ await s.init(n || {});
271
262
  } catch (o) {
272
263
  console.error("[BodhiProvider] Init failed:", o);
273
264
  }
274
265
  },
275
- [a]
266
+ [s]
276
267
  );
277
- T(() => {
278
- if (h.current) return;
279
- h.current = !0, (async () => {
280
- if (await _(), !S) return;
268
+ b(() => {
269
+ if (v.current) return;
270
+ v.current = !0, (async () => {
271
+ if (await x(), !m) return;
281
272
  const o = new URL(window.location.href);
282
- if (o.pathname !== D) return;
283
- const C = o.searchParams.get("code"), E = o.searchParams.get("state");
284
- !C || !E || A.current || (A.current = !0, re(a) && (p(!0), a.handleOAuthCallback(C, E).then(() => {
273
+ if (o.pathname !== _) return;
274
+ const L = o.searchParams.get("code"), k = o.searchParams.get("state");
275
+ !L || !k || E.current || (E.current = !0, re(s) && (g(!0), s.handleOAuthCallback(L, k).then(() => {
285
276
  window.history.replaceState({}, "", y);
286
- }).catch((O) => {
287
- console.error("OAuth callback failed:", O), g({
277
+ }).catch((M) => {
278
+ console.error("OAuth callback failed:", M), S({
288
279
  isLoggedIn: !1,
289
280
  error: {
290
- message: O instanceof Error ? O.message : "OAuth callback failed",
281
+ message: M instanceof Error ? M.message : "OAuth callback failed",
291
282
  code: "OAUTH_CALLBACK_FAILED"
292
283
  }
293
- }), p(!1), window.history.replaceState({}, "", y);
284
+ }), g(!1), window.history.replaceState({}, "", y);
294
285
  })));
295
286
  })();
296
- }, [_, a, S, D, y]);
287
+ }, [x, s, m, _, y]);
297
288
  const t = c(async () => {
298
- p(!0);
289
+ g(!0);
299
290
  try {
300
- await a.login();
291
+ await s.login();
301
292
  } catch (n) {
302
- g({
293
+ S({
303
294
  isLoggedIn: !1,
304
295
  error: {
305
296
  message: n instanceof Error ? n.message : "Login failed",
306
297
  code: "LOGIN_FAILED"
307
298
  }
308
- }), p(!1);
299
+ }), g(!1);
309
300
  }
310
- }, [a]), r = c(async () => {
301
+ }, [s]), r = c(async () => {
311
302
  try {
312
- await a.logout();
303
+ await s.logout();
313
304
  } catch (n) {
314
- g({
305
+ S({
315
306
  isLoggedIn: !1,
316
307
  error: {
317
308
  message: n instanceof Error ? n.message : "Logout failed",
@@ -319,31 +310,31 @@ function Se({
319
310
  }
320
311
  });
321
312
  }
322
- }, [a]), s = N(
313
+ }, [s]), a = I(
323
314
  () => ({
324
- client: a,
315
+ client: s,
325
316
  clientState: i,
326
317
  auth: f,
327
- authLoading: x,
318
+ authLoading: A,
328
319
  login: t,
329
320
  logout: r,
330
- showSetup: M,
321
+ showSetup: w,
331
322
  hideSetup: d,
332
- setupState: L
323
+ setupState: h
333
324
  }),
334
- [a, i, f, x, L, t, r, M, d]
325
+ [s, i, f, A, h, t, r, w, d]
335
326
  );
336
- return /* @__PURE__ */ G(z.Provider, { value: s, children: [
327
+ return /* @__PURE__ */ G(z.Provider, { value: a, children: [
337
328
  /* @__PURE__ */ K(
338
329
  ae,
339
330
  {
340
- client: a,
341
- modalHtmlPath: v,
331
+ client: s,
332
+ modalHtmlPath: C,
342
333
  hideSetup: d,
343
334
  onSetupReady: l,
344
- setupState: L,
335
+ setupState: h,
345
336
  basePath: y,
346
- logLevel: I
337
+ logLevel: D
347
338
  }
348
339
  ),
349
340
  e
@@ -370,37 +361,37 @@ function P(e) {
370
361
  function F(e) {
371
362
  return e.type === "initializing";
372
363
  }
373
- function k(e) {
364
+ function T(e) {
374
365
  return !(P(e) || F(e));
375
366
  }
376
367
  function oe(e) {
377
- return k(e) ? B(e) : !1;
368
+ return T(e) ? B(e) : !1;
378
369
  }
379
370
  function ie(e) {
380
371
  if (P(e))
381
372
  return { ready: !1, actualState: "not-initialized", mode: null };
382
373
  if (F(e))
383
374
  return { ready: !1, actualState: "initializing", mode: null };
384
- const a = U(e) ? "extension" : "direct", v = B(e), S = U(e) ? e.extension : e.server.status === "not-connected" ? "not-connected" : "ready";
385
- return { ready: v, actualState: S, mode: a };
375
+ const s = U(e) ? "extension" : "direct", C = B(e), m = U(e) ? e.extension : e.server.status === "not-connected" ? "not-connected" : "ready";
376
+ return { ready: C, actualState: m, mode: s };
386
377
  }
387
378
  function ue(e) {
388
- if (!k(e))
379
+ if (!T(e))
389
380
  return { ready: !1, actualState: "n/a" };
390
- const a = e.server;
381
+ const s = e.server;
391
382
  return {
392
- ready: a.status === "ready",
393
- actualState: a.status
383
+ ready: s.status === "ready",
384
+ actualState: s.status
394
385
  };
395
386
  }
396
387
  function ce(e) {
397
- return k(e) ? B(e) && e.server.status === "ready" : !1;
388
+ return T(e) ? B(e) && e.server.status === "ready" : !1;
398
389
  }
399
390
  const pe = {
400
391
  // Type guards
401
392
  isNotInitialized: P,
402
393
  isInitializing: F,
403
- isInitialized: k,
394
+ isInitialized: T,
404
395
  isReady: oe,
405
396
  // Derived state
406
397
  getClientInitState: ie,
@@ -412,7 +403,7 @@ export {
412
403
  z as BodhiReactContext,
413
404
  pe as ClientCtxState,
414
405
  Ce as REACT_BUILD_MODE,
415
- ye as createApiError,
406
+ ve as createApiError,
416
407
  he as createOperationError,
417
408
  ie as getClientInitState,
418
409
  ue as getServerState,
@@ -421,7 +412,7 @@ export {
421
412
  Oe as isApiResultSuccess,
422
413
  Ae as isAuthError,
423
414
  we as isAuthLoggedIn,
424
- k as isClientCtxInitialized,
415
+ T as isClientCtxInitialized,
425
416
  F as isClientCtxInitializing,
426
417
  P as isClientCtxNotInitialized,
427
418
  oe as isClientCtxReady,
@@ -1,5 +1,4 @@
1
1
  import { SetupState } from './state';
2
-
3
2
  /**
4
3
  * Central registry mapping message types to their payload/response shapes
5
4
  * Single source of truth - everything else is inferred!
@@ -1,5 +1,4 @@
1
1
  import { MessageType, RequestPayload, ResponsePayload } from './message-types';
2
-
3
2
  /** Branded type for type-safe request IDs */
4
3
  export type RequestId = string & {
5
4
  readonly __brand: 'RequestId';
@@ -2,7 +2,6 @@ import { Browser, EnvState, OS } from './platform';
2
2
  import { ExtensionState } from './extension';
3
3
  import { ServerState } from './server';
4
4
  import { LnaServerState, LnaState } from './lna';
5
-
6
5
  export declare enum SetupStep {
7
6
  PLATFORM_CHECK = "platform-check",
8
7
  SERVER_SETUP = "server-setup",
@@ -2,7 +2,6 @@ import { ExtensionState, ExtensionStateNotReady, ExtensionStateReady } from './e
2
2
  import { ServerState, ServerStateError, ServerStatePending, ServerStateReachable, ServerStateReady, ServerStateUnreachable } from './server';
3
3
  import { LnaServerState, LnaServerStateError, LnaServerStatePending, LnaServerStateReady, LnaServerStateResourceAdmin, LnaServerStateSetup, LnaState, LnaStateDenied, LnaStateGranted, LnaStatePrompt, LnaStateSkipped, LnaStateUnreachable, LnaStateUnsupported } from './lna';
4
4
  import { Browser, NotSupportedBrowser, NotSupportedOS, OS, SupportedBrowser, SupportedOS } from './platform';
5
-
6
5
  export declare function isExtensionStateReady(ext: ExtensionState): ext is ExtensionStateReady;
7
6
  export declare function isExtensionStateNotReady(ext: ExtensionState): ext is ExtensionStateNotReady;
8
7
  export declare function isServerStateReady(server: ServerState): server is ServerStateReady;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bodhiapp/bodhi-js-react",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "React bindings for Bodhi Browser SDK",
5
5
  "type": "module",
6
6
  "main": "dist/bodhi-react.cjs.js",
@@ -34,14 +34,15 @@
34
34
  "lint:fix": "prettier --write . && eslint . --ext .js,.jsx,.ts,.tsx --fix"
35
35
  },
36
36
  "dependencies": {
37
- "@bodhiapp/bodhi-js-core": "0.0.4",
38
- "@bodhiapp/ts-client": "^0.1.7"
37
+ "@bodhiapp/bodhi-js-core": "0.0.5",
38
+ "@bodhiapp/ts-client": "0.1.8"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "react": "^18.3.0 || ^19.0.0"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@eslint/js": "^9.23.0",
45
+ "@types/node": "^20.19.10",
45
46
  "@types/react": "^19.0.0",
46
47
  "@typescript-eslint/eslint-plugin": "8.28.0",
47
48
  "@typescript-eslint/parser": "8.28.0",
@@ -52,7 +53,7 @@
52
53
  "rimraf": "^6.0.1",
53
54
  "tslib": "^2.6.2",
54
55
  "typescript": "^5.8.3",
55
- "vite": "^5.2.0",
56
- "vite-plugin-dts": "^3.9.1"
56
+ "vite": "^7.1.12",
57
+ "vite-plugin-dts": "^4.5.4"
57
58
  }
58
59
  }