@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.
- package/dist/bodhi-browser-ext/src/types/bodhiext.d.ts +0 -1
- package/dist/bodhi-browser-ext/src/types/protocol.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/errors.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/facade-client-base.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/interface.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/logger.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/oauth.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/onboarding/config.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/onboarding/modal.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/onboarding/protocol-utils.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/platform.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/types/api.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/types/callback.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/types/client-state.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/types/config.d.ts +0 -1
- package/dist/bodhi-js-sdk/core/src/types/platform.d.ts +0 -1
- package/dist/bodhi-js-sdk/react/src/BodhiProvider.d.ts +0 -1
- package/dist/bodhi-js-sdk/react/src/SetupModalProcessor.d.ts +0 -1
- package/dist/bodhi-js-sdk/react/src/client-ctx.d.ts +0 -1
- package/dist/bodhi-react.cjs.js +2 -2
- package/dist/bodhi-react.esm.d.ts +1 -0
- package/dist/bodhi-react.esm.js +133 -142
- package/dist/setup-modal/src/types/message-types.d.ts +0 -1
- package/dist/setup-modal/src/types/protocol.d.ts +0 -1
- package/dist/setup-modal/src/types/state.d.ts +0 -1
- package/dist/setup-modal/src/types/type-guards.d.ts +0 -1
- 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
|
|
@@ -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 { 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,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;
|
package/dist/bodhi-react.cjs.js
CHANGED
|
@@ -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"),
|
|
2
|
-
`,JSON.stringify(r,null,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"),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;
|
package/dist/bodhi-react.esm.js
CHANGED
|
@@ -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
|
|
4
|
-
import { useMemo as
|
|
5
|
-
const
|
|
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:
|
|
22
|
-
hideSetup:
|
|
23
|
-
onSetupReady:
|
|
24
|
-
setupState:
|
|
21
|
+
modalHtmlPath: s,
|
|
22
|
+
hideSetup: C,
|
|
23
|
+
onSetupReady: m,
|
|
24
|
+
setupState: _,
|
|
25
25
|
basePath: y = "/",
|
|
26
|
-
logLevel:
|
|
26
|
+
logLevel: D = "warn"
|
|
27
27
|
}) {
|
|
28
|
-
const
|
|
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 =
|
|
31
|
+
), f = N(null), S = c(
|
|
32
32
|
(t) => t === "direct" ? "lna" : t === "extension" ? "extension" : null,
|
|
33
33
|
[]
|
|
34
|
-
),
|
|
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
|
-
}, []),
|
|
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
|
-
}, []),
|
|
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
|
-
}, []),
|
|
93
|
+
}, []), O = c(
|
|
94
94
|
(t, r) => {
|
|
95
95
|
if (t.server.status !== "pending-extension-ready") {
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
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
|
|
102
|
-
if (
|
|
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
|
-
),
|
|
109
|
-
(t, r,
|
|
108
|
+
), w = c(
|
|
109
|
+
(t, r, a) => {
|
|
110
110
|
if (r === "skipped")
|
|
111
|
-
return { status: "skipped", serverUrl:
|
|
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:
|
|
114
|
+
return n.status === "ready" || n.status === "setup" || n.status === "resource-admin" ? { status: "granted", serverUrl: a } : {
|
|
115
115
|
status: "unreachable",
|
|
116
|
-
serverUrl:
|
|
116
|
+
serverUrl: a,
|
|
117
117
|
error: { message: n.error.message, code: "lna-unreachable" }
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
-
return r === "granted" ? { status: "granted", serverUrl:
|
|
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,
|
|
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
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
return e.getConnectionMode() === null && (Q(o) ? await e.setConnectionMode("direct") : X(n) && await e.setConnectionMode("extension")), u.isServerInstallConfirmed() ||
|
|
133
|
-
extension:
|
|
134
|
-
server:
|
|
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:
|
|
137
|
-
env: { browser: r, os:
|
|
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:
|
|
141
|
+
selectedConnection: S(e.getConnectionMode())
|
|
142
142
|
};
|
|
143
143
|
},
|
|
144
144
|
[
|
|
145
145
|
e,
|
|
146
146
|
u,
|
|
147
|
-
|
|
148
|
-
p,
|
|
149
|
-
L,
|
|
147
|
+
A,
|
|
150
148
|
g,
|
|
151
|
-
|
|
152
|
-
|
|
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:
|
|
164
|
+
selectedConnection: S(e.getConnectionMode())
|
|
165
165
|
};
|
|
166
|
-
}, [u, e,
|
|
166
|
+
}, [u, e, S]), x = I(
|
|
167
167
|
() => ({
|
|
168
|
-
[
|
|
169
|
-
[
|
|
170
|
-
|
|
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
|
|
176
|
-
`, JSON.stringify(r, null, 2)),
|
|
174
|
+
return v.info(`MODAL_REFRESH: state refreshed
|
|
175
|
+
`, JSON.stringify(r, null, 2)), i.current?.updateState(l()), { setupState: r };
|
|
177
176
|
},
|
|
178
|
-
[
|
|
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
|
|
183
|
-
if (
|
|
184
|
-
const
|
|
185
|
-
if (
|
|
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
|
|
188
|
-
return f.current =
|
|
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,
|
|
190
|
+
return f.current = n, i.current?.updateState(l()), { success: !1 };
|
|
193
191
|
},
|
|
194
|
-
[
|
|
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,
|
|
195
|
+
return f.current = t, i.current?.updateState(l()), { success: !0 };
|
|
199
196
|
},
|
|
200
|
-
[
|
|
201
|
-
|
|
197
|
+
[p.MODAL_CLOSE]: () => {
|
|
198
|
+
C();
|
|
202
199
|
},
|
|
203
|
-
[
|
|
204
|
-
|
|
200
|
+
[p.MODAL_COMPLETE]: () => {
|
|
201
|
+
C();
|
|
205
202
|
},
|
|
206
|
-
[
|
|
207
|
-
|
|
208
|
-
|
|
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
|
-
[
|
|
209
|
+
[v, e, u, d, l, h, C]
|
|
217
210
|
);
|
|
218
|
-
return
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
}) : !
|
|
228
|
-
}, [
|
|
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:
|
|
235
|
-
modalHtmlPath:
|
|
236
|
-
handleCallback:
|
|
237
|
-
callbackPath:
|
|
225
|
+
client: s,
|
|
226
|
+
modalHtmlPath: C,
|
|
227
|
+
handleCallback: m = !0,
|
|
228
|
+
callbackPath: _ = "/callback",
|
|
238
229
|
basePath: y = "/",
|
|
239
|
-
logLevel:
|
|
230
|
+
logLevel: D = "warn"
|
|
240
231
|
}) {
|
|
241
|
-
const
|
|
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,
|
|
245
|
-
|
|
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
|
-
|
|
243
|
+
S(o.state), g(!1);
|
|
253
244
|
break;
|
|
254
245
|
}
|
|
255
246
|
};
|
|
256
|
-
return
|
|
257
|
-
|
|
247
|
+
return s.setStateCallback(n), () => {
|
|
248
|
+
s.setStateCallback(te);
|
|
258
249
|
};
|
|
259
|
-
}, [
|
|
260
|
-
const
|
|
261
|
-
|
|
250
|
+
}, [s]);
|
|
251
|
+
const w = c(async () => {
|
|
252
|
+
O("loading");
|
|
262
253
|
}, []), d = c(() => {
|
|
263
|
-
|
|
254
|
+
O("ready");
|
|
264
255
|
}, []), l = c(() => {
|
|
265
|
-
|
|
266
|
-
}, []),
|
|
256
|
+
O("loaded");
|
|
257
|
+
}, []), x = c(
|
|
267
258
|
async (n) => {
|
|
268
259
|
u({ type: "initializing" });
|
|
269
260
|
try {
|
|
270
|
-
await
|
|
261
|
+
await s.init(n || {});
|
|
271
262
|
} catch (o) {
|
|
272
263
|
console.error("[BodhiProvider] Init failed:", o);
|
|
273
264
|
}
|
|
274
265
|
},
|
|
275
|
-
[
|
|
266
|
+
[s]
|
|
276
267
|
);
|
|
277
|
-
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
if (await
|
|
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 !==
|
|
283
|
-
const
|
|
284
|
-
!
|
|
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((
|
|
287
|
-
console.error("OAuth callback failed:",
|
|
277
|
+
}).catch((M) => {
|
|
278
|
+
console.error("OAuth callback failed:", M), S({
|
|
288
279
|
isLoggedIn: !1,
|
|
289
280
|
error: {
|
|
290
|
-
message:
|
|
281
|
+
message: M instanceof Error ? M.message : "OAuth callback failed",
|
|
291
282
|
code: "OAUTH_CALLBACK_FAILED"
|
|
292
283
|
}
|
|
293
|
-
}),
|
|
284
|
+
}), g(!1), window.history.replaceState({}, "", y);
|
|
294
285
|
})));
|
|
295
286
|
})();
|
|
296
|
-
}, [
|
|
287
|
+
}, [x, s, m, _, y]);
|
|
297
288
|
const t = c(async () => {
|
|
298
|
-
|
|
289
|
+
g(!0);
|
|
299
290
|
try {
|
|
300
|
-
await
|
|
291
|
+
await s.login();
|
|
301
292
|
} catch (n) {
|
|
302
|
-
|
|
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
|
-
}),
|
|
299
|
+
}), g(!1);
|
|
309
300
|
}
|
|
310
|
-
}, [
|
|
301
|
+
}, [s]), r = c(async () => {
|
|
311
302
|
try {
|
|
312
|
-
await
|
|
303
|
+
await s.logout();
|
|
313
304
|
} catch (n) {
|
|
314
|
-
|
|
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
|
-
}, [
|
|
313
|
+
}, [s]), a = I(
|
|
323
314
|
() => ({
|
|
324
|
-
client:
|
|
315
|
+
client: s,
|
|
325
316
|
clientState: i,
|
|
326
317
|
auth: f,
|
|
327
|
-
authLoading:
|
|
318
|
+
authLoading: A,
|
|
328
319
|
login: t,
|
|
329
320
|
logout: r,
|
|
330
|
-
showSetup:
|
|
321
|
+
showSetup: w,
|
|
331
322
|
hideSetup: d,
|
|
332
|
-
setupState:
|
|
323
|
+
setupState: h
|
|
333
324
|
}),
|
|
334
|
-
[
|
|
325
|
+
[s, i, f, A, h, t, r, w, d]
|
|
335
326
|
);
|
|
336
|
-
return /* @__PURE__ */ G(z.Provider, { value:
|
|
327
|
+
return /* @__PURE__ */ G(z.Provider, { value: a, children: [
|
|
337
328
|
/* @__PURE__ */ K(
|
|
338
329
|
ae,
|
|
339
330
|
{
|
|
340
|
-
client:
|
|
341
|
-
modalHtmlPath:
|
|
331
|
+
client: s,
|
|
332
|
+
modalHtmlPath: C,
|
|
342
333
|
hideSetup: d,
|
|
343
334
|
onSetupReady: l,
|
|
344
|
-
setupState:
|
|
335
|
+
setupState: h,
|
|
345
336
|
basePath: y,
|
|
346
|
-
logLevel:
|
|
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
|
|
364
|
+
function T(e) {
|
|
374
365
|
return !(P(e) || F(e));
|
|
375
366
|
}
|
|
376
367
|
function oe(e) {
|
|
377
|
-
return
|
|
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
|
|
385
|
-
return { ready:
|
|
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 (!
|
|
379
|
+
if (!T(e))
|
|
389
380
|
return { ready: !1, actualState: "n/a" };
|
|
390
|
-
const
|
|
381
|
+
const s = e.server;
|
|
391
382
|
return {
|
|
392
|
-
ready:
|
|
393
|
-
actualState:
|
|
383
|
+
ready: s.status === "ready",
|
|
384
|
+
actualState: s.status
|
|
394
385
|
};
|
|
395
386
|
}
|
|
396
387
|
function ce(e) {
|
|
397
|
-
return
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
415
|
+
T as isClientCtxInitialized,
|
|
425
416
|
F as isClientCtxInitializing,
|
|
426
417
|
P as isClientCtxNotInitialized,
|
|
427
418
|
oe as isClientCtxReady,
|
|
@@ -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.
|
|
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.
|
|
38
|
-
"@bodhiapp/ts-client": "
|
|
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": "^
|
|
56
|
-
"vite-plugin-dts": "^
|
|
56
|
+
"vite": "^7.1.12",
|
|
57
|
+
"vite-plugin-dts": "^4.5.4"
|
|
57
58
|
}
|
|
58
59
|
}
|