@bodhiapp/bodhi-js 0.0.1
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/README.md +26 -0
- package/dist/bodhi-browser-ext/src/types/bodhiext.d.ts +202 -0
- package/dist/bodhi-browser-ext/src/types/common.d.ts +36 -0
- package/dist/bodhi-browser-ext/src/types/index.d.ts +6 -0
- package/dist/bodhi-browser-ext/src/types/protocol.d.ts +223 -0
- package/dist/bodhi-js-sdk/core/src/direct-client-base.d.ts +129 -0
- package/dist/bodhi-js-sdk/core/src/errors.d.ts +23 -0
- package/dist/bodhi-js-sdk/core/src/facade-client-base.d.ts +130 -0
- package/dist/bodhi-js-sdk/core/src/index.d.ts +19 -0
- package/dist/bodhi-js-sdk/core/src/interface.d.ts +228 -0
- package/dist/bodhi-js-sdk/core/src/logger.d.ts +13 -0
- package/dist/bodhi-js-sdk/core/src/oauth.d.ts +45 -0
- package/dist/bodhi-js-sdk/core/src/onboarding/config.d.ts +10 -0
- package/dist/bodhi-js-sdk/core/src/onboarding/index.d.ts +5 -0
- package/dist/bodhi-js-sdk/core/src/onboarding/modal.d.ts +80 -0
- package/dist/bodhi-js-sdk/core/src/onboarding/protocol-utils.d.ts +33 -0
- package/dist/bodhi-js-sdk/core/src/platform.d.ts +11 -0
- package/dist/bodhi-js-sdk/core/src/storage.d.ts +81 -0
- package/dist/bodhi-js-sdk/core/src/types/api.d.ts +34 -0
- package/dist/bodhi-js-sdk/core/src/types/callback.d.ts +23 -0
- package/dist/bodhi-js-sdk/core/src/types/client-state.d.ts +191 -0
- package/dist/bodhi-js-sdk/core/src/types/config.d.ts +26 -0
- package/dist/bodhi-js-sdk/core/src/types/html.d.ts +9 -0
- package/dist/bodhi-js-sdk/core/src/types/index.d.ts +15 -0
- package/dist/bodhi-js-sdk/core/src/types/platform.d.ts +16 -0
- package/dist/bodhi-js-sdk/core/src/types/user-info.d.ts +59 -0
- package/dist/bodhi-js-sdk/web/src/constants.d.ts +9 -0
- package/dist/bodhi-js-sdk/web/src/direct-client.d.ts +24 -0
- package/dist/bodhi-js-sdk/web/src/ext-client.d.ts +151 -0
- package/dist/bodhi-js-sdk/web/src/facade-client.d.ts +43 -0
- package/dist/bodhi-js-sdk/web/src/index.d.ts +5 -0
- package/dist/bodhi-js-sdk/web/src/interface.d.ts +4 -0
- package/dist/bodhi-web.cjs.js +749 -0
- package/dist/bodhi-web.cjs.js.map +1 -0
- package/dist/bodhi-web.esm.d.ts +1 -0
- package/dist/bodhi-web.esm.js +749 -0
- package/dist/bodhi-web.esm.js.map +1 -0
- package/dist/setup-modal/src/types/extension.d.ts +24 -0
- package/dist/setup-modal/src/types/index.d.ts +20 -0
- package/dist/setup-modal/src/types/lna.d.ts +56 -0
- package/dist/setup-modal/src/types/message-types.d.ts +169 -0
- package/dist/setup-modal/src/types/platform.d.ts +32 -0
- package/dist/setup-modal/src/types/protocol.d.ts +71 -0
- package/dist/setup-modal/src/types/server.d.ts +63 -0
- package/dist/setup-modal/src/types/state.d.ts +43 -0
- package/dist/setup-modal/src/types/type-guards.d.ts +27 -0
- package/package.json +54 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { CreateChatCompletionStreamResponse } from '@bodhiapp/ts-client';
|
|
2
|
+
import { IConnectionClient } from './interface';
|
|
3
|
+
import { Logger } from './logger';
|
|
4
|
+
import { BodhiClientUserPrefsManager } from './storage';
|
|
5
|
+
import { ApiResponseResult, AuthLoggedIn, AuthLoggedOut, AuthState, BackendServerState, ClientState, ConnectionMode, DirectState, ExtensionState, InitParams, SerializedClientState, SerializedDirectState, SerializedExtensionState, StateChange, StateChangeCallback } from './types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Base facade client with common delegation logic
|
|
9
|
+
*
|
|
10
|
+
* @template TConfig - Configuration type for this facade
|
|
11
|
+
* @template TExtClient - Extension client type (implements IConnectionClient with SerializedExtensionState)
|
|
12
|
+
* @template TDirectClient - Direct client type (implements IConnectionClient with SerializedDirectState)
|
|
13
|
+
*/
|
|
14
|
+
export declare abstract class BaseFacadeClient<TConfig, TExtClient extends IConnectionClient<unknown, SerializedExtensionState>, TDirectClient extends IConnectionClient<unknown, SerializedDirectState>> {
|
|
15
|
+
protected logger: Logger;
|
|
16
|
+
protected extClient: TExtClient;
|
|
17
|
+
protected directClient: TDirectClient;
|
|
18
|
+
protected prefs: BodhiClientUserPrefsManager;
|
|
19
|
+
protected connectionMode: ConnectionMode | null;
|
|
20
|
+
protected authClientId: string;
|
|
21
|
+
protected config: TConfig;
|
|
22
|
+
protected onStateChange: StateChangeCallback;
|
|
23
|
+
constructor(authClientId: string, config: TConfig, onStateChange?: StateChangeCallback, storagePrefix?: string);
|
|
24
|
+
/**
|
|
25
|
+
* Create logger instance
|
|
26
|
+
* Subclasses extract logLevel from their specific config type
|
|
27
|
+
*/
|
|
28
|
+
protected abstract createLogger(config: TConfig): Logger;
|
|
29
|
+
/**
|
|
30
|
+
* Create extension-based client (ExtClient or WindowBodhiextClient)
|
|
31
|
+
*/
|
|
32
|
+
protected abstract createExtClient(config: TConfig, onStateChange: (change: StateChange) => void): TExtClient;
|
|
33
|
+
/**
|
|
34
|
+
* Create direct HTTP client (DirectExtClient or DirectWebClient)
|
|
35
|
+
*/
|
|
36
|
+
protected abstract createDirectClient(authClientId: string, config: TConfig, onStateChange: (change: StateChange) => void): TDirectClient;
|
|
37
|
+
/**
|
|
38
|
+
* Notify client state change by calling facade's callback with discriminated union
|
|
39
|
+
*/
|
|
40
|
+
private notifyStateChange;
|
|
41
|
+
/**
|
|
42
|
+
* Handle state changes from internal clients (extClient or directClient)
|
|
43
|
+
* For client state changes, notifyStateChange that persists and notifies
|
|
44
|
+
* For auth state changes, notify the callback directly
|
|
45
|
+
*/
|
|
46
|
+
private handleInternalStateChange;
|
|
47
|
+
/**
|
|
48
|
+
* Serialize current state for persistence
|
|
49
|
+
* Returns SerializedClientState with nested client states
|
|
50
|
+
*/
|
|
51
|
+
serialize(): SerializedClientState;
|
|
52
|
+
/**
|
|
53
|
+
* Debug dump of facade client internal state
|
|
54
|
+
* Aggregates debug info from both internal clients
|
|
55
|
+
*/
|
|
56
|
+
debug(): Promise<Record<string, unknown>>;
|
|
57
|
+
/**
|
|
58
|
+
* Persist current state to storage
|
|
59
|
+
*/
|
|
60
|
+
persist(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Set or update the state change callback
|
|
63
|
+
*/
|
|
64
|
+
setStateCallback(callback: StateChangeCallback): void;
|
|
65
|
+
/**
|
|
66
|
+
* Check if connection mode is null or direct
|
|
67
|
+
* Used for delegation - prefers direct on fresh install
|
|
68
|
+
*/
|
|
69
|
+
protected isNotSetOrDirect(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Initialize client based on current connectionMode
|
|
72
|
+
*
|
|
73
|
+
* State Management:
|
|
74
|
+
* - Facade owns persistence via prefs - savedState param is NOT used
|
|
75
|
+
* - Restores connectionMode and internal client states from prefs.getSerializedClientState()
|
|
76
|
+
* - On fresh install (no saved state), defaults to connectionMode: null
|
|
77
|
+
*
|
|
78
|
+
* InitParams (optional):
|
|
79
|
+
* - serverUrl: Direct mode server URL (overrides saved state)
|
|
80
|
+
* - testConnection: Test server connectivity during init
|
|
81
|
+
* - timeoutMs: Extension mode discovery timeout
|
|
82
|
+
* - selectedConnection, savedState: Internal use only (not for external callers)
|
|
83
|
+
*
|
|
84
|
+
* Eager Connection Detection (when connectionMode is null):
|
|
85
|
+
* Tries direct first, then extension, auto-selecting first one with server ready
|
|
86
|
+
*/
|
|
87
|
+
init(params?: InitParams): Promise<ExtensionState | DirectState>;
|
|
88
|
+
getState(): ClientState;
|
|
89
|
+
isClientInitialized(): boolean;
|
|
90
|
+
isServerReady(): boolean;
|
|
91
|
+
sendExtRequest<TParams = void, TRes = unknown>(action: string, params?: TParams): Promise<TRes>;
|
|
92
|
+
sendApiRequest<TReq = void, TRes = unknown>(method: string, endpoint: string, body?: TReq, headers?: Record<string, string>, authenticated?: boolean): Promise<ApiResponseResult<TRes>>;
|
|
93
|
+
login(): Promise<AuthLoggedIn>;
|
|
94
|
+
logout(): Promise<AuthLoggedOut>;
|
|
95
|
+
getAuthState(): Promise<AuthState>;
|
|
96
|
+
pingApi(): Promise<ApiResponseResult<{
|
|
97
|
+
message: string;
|
|
98
|
+
}>>;
|
|
99
|
+
fetchModels(): Promise<ApiResponseResult<{
|
|
100
|
+
data: Array<{
|
|
101
|
+
id: string;
|
|
102
|
+
object: string;
|
|
103
|
+
}>;
|
|
104
|
+
}>>;
|
|
105
|
+
getServerState(): Promise<BackendServerState>;
|
|
106
|
+
stream<TReq = unknown, TRes = unknown>(method: string, endpoint: string, body?: TReq, headers?: Record<string, string>, authenticated?: boolean): AsyncGenerator<TRes>;
|
|
107
|
+
streamChat(model: string, prompt: string, authenticated?: boolean): AsyncGenerator<CreateChatCompletionStreamResponse>;
|
|
108
|
+
getConnectionMode(): ConnectionMode | null;
|
|
109
|
+
setConnectionMode(mode: ConnectionMode): Promise<ClientState>;
|
|
110
|
+
/**
|
|
111
|
+
* Test extension connectivity regardless of current connection mode
|
|
112
|
+
* Fresh connection test - injects testConnection: true internally
|
|
113
|
+
* @param timeoutMs - Optional timeout for extension discovery
|
|
114
|
+
*/
|
|
115
|
+
testExtensionConnectivity(timeoutMs?: number): Promise<ExtensionState>;
|
|
116
|
+
/**
|
|
117
|
+
* Test direct server connectivity
|
|
118
|
+
* Fresh connection test - injects testConnection: true internally
|
|
119
|
+
* @param serverUrl - Optional server URL to test. If not provided, uses saved serverUrl from state
|
|
120
|
+
*/
|
|
121
|
+
testDirectConnectivity(serverUrl?: string): Promise<DirectState>;
|
|
122
|
+
/**
|
|
123
|
+
* Get current extension state (regardless of current connection mode)
|
|
124
|
+
*/
|
|
125
|
+
getExtensionState(): Promise<ExtensionState>;
|
|
126
|
+
/**
|
|
127
|
+
* Get current direct server state
|
|
128
|
+
*/
|
|
129
|
+
getDirectState(): Promise<DirectState>;
|
|
130
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @bodhiapp/bodhi-js-core - Minimal shared types and interfaces
|
|
3
|
+
*
|
|
4
|
+
* This package contains the minimal shared code between ext and web SDKs:
|
|
5
|
+
* - Types (ApiResponseResult, ClientState, UserInfo, etc.)
|
|
6
|
+
* - Error factories (createApiError, createOperationError)
|
|
7
|
+
* - Logger (centralized logging)
|
|
8
|
+
* - UIClient interface (base interface)
|
|
9
|
+
*/
|
|
10
|
+
export * from './types';
|
|
11
|
+
export * from './logger';
|
|
12
|
+
export * from './interface';
|
|
13
|
+
export * from './platform';
|
|
14
|
+
export * from './storage';
|
|
15
|
+
export * from './onboarding';
|
|
16
|
+
export * from './oauth';
|
|
17
|
+
export * from './direct-client-base';
|
|
18
|
+
export * from './facade-client-base';
|
|
19
|
+
export { isOperationError, type OperationError } from '../../../bodhi-browser-ext/src/types';
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { CreateChatCompletionStreamResponse } from '@bodhiapp/ts-client';
|
|
2
|
+
import { ApiResponseResult, AuthLoggedIn, AuthLoggedOut, AuthState, BackendServerState, ClientState, ConnectionMode, DirectState, ExtensionState, InitParams, StateChangeCallback } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ConnectionClient - Base interface for all client implementations
|
|
6
|
+
*
|
|
7
|
+
* Defines common interface for:
|
|
8
|
+
* - IExtensionClient (chrome.runtime or window.bodhiext)
|
|
9
|
+
* - DirectClient (direct HTTP fetch)
|
|
10
|
+
*
|
|
11
|
+
* Includes both connection methods (API calls, streaming) and auth methods.
|
|
12
|
+
*
|
|
13
|
+
* @template IParams - The init params type for this client
|
|
14
|
+
* @template SerialState - The serialized state type for persistence
|
|
15
|
+
*/
|
|
16
|
+
export interface IConnectionClient<IParams = unknown, SerialState = unknown> {
|
|
17
|
+
/**
|
|
18
|
+
* Initialize client discovery/connectivity
|
|
19
|
+
* - IExtensionClient: Discover bodhi-browser-ext extension
|
|
20
|
+
* - DirectClient: Test HTTP connectivity to server
|
|
21
|
+
*
|
|
22
|
+
* @param params - ExtParams or DirectParams (discriminated by serverUrl presence)
|
|
23
|
+
* @returns ClientState (ExtensionState or DirectState based on active connection mode)
|
|
24
|
+
*/
|
|
25
|
+
init(params: IParams): Promise<ClientState>;
|
|
26
|
+
/**
|
|
27
|
+
* Get current client state
|
|
28
|
+
* @returns ClientState with status and connectionMode
|
|
29
|
+
*/
|
|
30
|
+
getState(): ClientState;
|
|
31
|
+
/**
|
|
32
|
+
* Check if client is initialized (has handle/url configured)
|
|
33
|
+
* - DirectClient: serverUrl is set
|
|
34
|
+
* - ExtensionClient: extension is 'ready'
|
|
35
|
+
* @returns true if client is ready to make requests
|
|
36
|
+
*/
|
|
37
|
+
isClientInitialized(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Check if backend server is ready (status === 'ready')
|
|
40
|
+
* @returns true if server is connected and ready
|
|
41
|
+
*/
|
|
42
|
+
isServerReady(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Send API request to local server
|
|
45
|
+
* @param authenticated - If true, injects access token automatically
|
|
46
|
+
* @returns ApiResponseResult with response or operation error
|
|
47
|
+
*/
|
|
48
|
+
sendApiRequest<TReq = void, TRes = unknown>(method: string, endpoint: string, body?: TReq, headers?: Record<string, string>, authenticated?: boolean): Promise<ApiResponseResult<TRes>>;
|
|
49
|
+
/**
|
|
50
|
+
* Ping API endpoint
|
|
51
|
+
* @returns ApiResponseResult with ping response
|
|
52
|
+
*/
|
|
53
|
+
pingApi(): Promise<ApiResponseResult<{
|
|
54
|
+
message: string;
|
|
55
|
+
}>>;
|
|
56
|
+
/**
|
|
57
|
+
* Fetch available models from /v1/models
|
|
58
|
+
* @returns ApiResponseResult with models list
|
|
59
|
+
*/
|
|
60
|
+
fetchModels(): Promise<ApiResponseResult<{
|
|
61
|
+
data: Array<{
|
|
62
|
+
id: string;
|
|
63
|
+
object: string;
|
|
64
|
+
}>;
|
|
65
|
+
}>>;
|
|
66
|
+
/**
|
|
67
|
+
* Get backend server state
|
|
68
|
+
* Calls /bodhi/v1/info and returns structured server state
|
|
69
|
+
* @returns BackendServerState with status and version
|
|
70
|
+
*/
|
|
71
|
+
getServerState(): Promise<BackendServerState>;
|
|
72
|
+
/**
|
|
73
|
+
* Generic streaming request
|
|
74
|
+
* - IExtensionClient: chrome.runtime.connect port or window.bodhiext stream
|
|
75
|
+
* - DirectClient: Server-Sent Events (SSE) via fetch
|
|
76
|
+
*
|
|
77
|
+
* @returns AsyncGenerator yielding response chunks
|
|
78
|
+
*/
|
|
79
|
+
stream<TReq = unknown, TRes = unknown>(method: string, endpoint: string, body?: TReq, headers?: Record<string, string>, authenticated?: boolean): AsyncGenerator<TRes>;
|
|
80
|
+
/**
|
|
81
|
+
* Chat streaming (convenience wrapper for stream)
|
|
82
|
+
* @returns AsyncGenerator yielding chat completion chunks
|
|
83
|
+
*/
|
|
84
|
+
streamChat(model: string, prompt: string, authenticated?: boolean): AsyncGenerator<CreateChatCompletionStreamResponse>;
|
|
85
|
+
/**
|
|
86
|
+
* Login via OAuth
|
|
87
|
+
* - IExtensionClient: Delegates to extension (chrome.identity or browser redirect)
|
|
88
|
+
* - DirectClient: Direct HTTP OAuth flow
|
|
89
|
+
* @returns AuthLoggedIn with login state and user info
|
|
90
|
+
*/
|
|
91
|
+
login(): Promise<AuthLoggedIn>;
|
|
92
|
+
/**
|
|
93
|
+
* Logout and revoke tokens
|
|
94
|
+
* @returns AuthLoggedOut with logged out state
|
|
95
|
+
*/
|
|
96
|
+
logout(): Promise<AuthLoggedOut>;
|
|
97
|
+
/**
|
|
98
|
+
* Get current authentication state
|
|
99
|
+
* @returns AuthState (discriminated union: AuthLoggedIn | AuthLoggedOut)
|
|
100
|
+
*/
|
|
101
|
+
getAuthState(): Promise<AuthState>;
|
|
102
|
+
/**
|
|
103
|
+
* Set or update the state change callback
|
|
104
|
+
* Allows setting callback after construction (for React dependency injection)
|
|
105
|
+
* @param callback - Callback invoked on client state or auth state changes
|
|
106
|
+
*/
|
|
107
|
+
setStateCallback(callback: StateChangeCallback): void;
|
|
108
|
+
/**
|
|
109
|
+
* Serialize client state for persistence
|
|
110
|
+
* @returns Serialized state suitable for localStorage/chrome.storage
|
|
111
|
+
*/
|
|
112
|
+
serialize(): SerialState;
|
|
113
|
+
/**
|
|
114
|
+
* Debug dump of client internal state
|
|
115
|
+
* Returns free-form object for console.log or UI display
|
|
116
|
+
* Includes transient state (unlike serialize which is for persistence)
|
|
117
|
+
* Fetches live authState via async call
|
|
118
|
+
* @returns Promise resolving to object with internal state for debugging
|
|
119
|
+
*/
|
|
120
|
+
debug(): Promise<Record<string, unknown>>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* IExtensionClient - Extension-specific client interface
|
|
124
|
+
*
|
|
125
|
+
* Extends IConnectionClient with sendExtRequest for direct extension communication.
|
|
126
|
+
*
|
|
127
|
+
* Implementations:
|
|
128
|
+
* - Ext2ExtClient: chrome.runtime.sendMessage (extension context)
|
|
129
|
+
* - Web2ExtClient: window.bodhiext (web page context)
|
|
130
|
+
*
|
|
131
|
+
* @template IParams - The init params type for this client
|
|
132
|
+
* @template SerialState - The serialized state type for persistence
|
|
133
|
+
*/
|
|
134
|
+
export interface IExtensionClient<IParams = unknown, SerialState = unknown> extends IConnectionClient<IParams, SerialState> {
|
|
135
|
+
/**
|
|
136
|
+
* Send extension request
|
|
137
|
+
* Communicates with bodhi-browser-ext extension via:
|
|
138
|
+
* - chrome.runtime.sendMessage (extension context)
|
|
139
|
+
* - window.bodhiext (web context)
|
|
140
|
+
*
|
|
141
|
+
* @param action - Extension action (e.g., 'DISCOVER_EXTENSION', 'LOGIN')
|
|
142
|
+
* @param params - Action parameters
|
|
143
|
+
* @returns Response from extension
|
|
144
|
+
*/
|
|
145
|
+
sendExtRequest<TParams = void, TRes = unknown>(action: string, params?: TParams): Promise<TRes>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* DirectClient - Direct HTTP client interface
|
|
149
|
+
*
|
|
150
|
+
* Extends IConnectionClient with no additional methods.
|
|
151
|
+
* Communicates directly with local server via HTTP fetch (no extension intermediary).
|
|
152
|
+
*
|
|
153
|
+
* @template IParams - The init params type for this client
|
|
154
|
+
* @template SerialState - The serialized state type for persistence
|
|
155
|
+
*/
|
|
156
|
+
export interface IDirectClient<IParams = unknown, SerialState = unknown> extends IConnectionClient<IParams, SerialState> {
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* UIClient - Facade client with connection mode switching
|
|
160
|
+
*
|
|
161
|
+
* Combination of ConnectionClient + connection mode management.
|
|
162
|
+
* Internally holds both IExtensionClient and DirectClient, delegates to active client.
|
|
163
|
+
*
|
|
164
|
+
* Usage:
|
|
165
|
+
* ```
|
|
166
|
+
* const uiClient: UIClient = new UIClientImpl(extensionClient);
|
|
167
|
+
* await uiClient.init({ serverUrl: 'http://localhost:1135' }); // Init direct
|
|
168
|
+
* uiClient.setConnectionMode('extension'); // Switch to extension mode
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
export type UIClient = IConnectionClient<InitParams> & {
|
|
172
|
+
/**
|
|
173
|
+
* Set connection mode and switch active client
|
|
174
|
+
* @param mode - 'direct' or 'extension'
|
|
175
|
+
* @returns Promise with connection mode result
|
|
176
|
+
*/
|
|
177
|
+
setConnectionMode(mode: ConnectionMode): Promise<ClientState>;
|
|
178
|
+
/**
|
|
179
|
+
* Get current connection mode
|
|
180
|
+
* @returns 'direct', 'extension', or null if not set
|
|
181
|
+
*/
|
|
182
|
+
getConnectionMode(): ConnectionMode | null;
|
|
183
|
+
/**
|
|
184
|
+
* Test extension connectivity regardless of current connection mode
|
|
185
|
+
* Initializes extension client and tests backend server connection
|
|
186
|
+
* @param timeoutMs - Optional timeout for extension discovery
|
|
187
|
+
* @returns ExtensionState with extension status and server state
|
|
188
|
+
*/
|
|
189
|
+
testExtensionConnectivity(timeoutMs?: number): Promise<ExtensionState>;
|
|
190
|
+
/**
|
|
191
|
+
* Test direct server connectivity
|
|
192
|
+
* Initializes direct client and tests backend server connection
|
|
193
|
+
* @param serverUrl - Optional server URL to test. If not provided, uses saved serverUrl from state
|
|
194
|
+
* @returns DirectState with server status and URL
|
|
195
|
+
*/
|
|
196
|
+
testDirectConnectivity(serverUrl?: string): Promise<DirectState>;
|
|
197
|
+
/**
|
|
198
|
+
* Get current extension state (regardless of current connection mode)
|
|
199
|
+
* Returns extension status and backend server state
|
|
200
|
+
* @returns ExtensionState
|
|
201
|
+
*/
|
|
202
|
+
getExtensionState(): Promise<ExtensionState>;
|
|
203
|
+
/**
|
|
204
|
+
* Get current direct server state (if configured)
|
|
205
|
+
* Returns direct server status and URL
|
|
206
|
+
* @returns DirectState
|
|
207
|
+
*/
|
|
208
|
+
getDirectState(): Promise<DirectState>;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Web-specific UIClient interface with OAuth callback handling
|
|
212
|
+
* Defines the contract for web mode clients
|
|
213
|
+
*/
|
|
214
|
+
export interface IWebUIClient extends UIClient {
|
|
215
|
+
/**
|
|
216
|
+
* Handle OAuth callback after redirect (web mode only)
|
|
217
|
+
* @param code - Authorization code from OAuth provider
|
|
218
|
+
* @param state - State parameter for CSRF protection
|
|
219
|
+
* @returns AuthLoggedIn with login state and user info
|
|
220
|
+
*/
|
|
221
|
+
handleOAuthCallback(code: string, state: string): Promise<AuthLoggedIn>;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Type guard to check if client has OAuth callback handling (web mode)
|
|
225
|
+
* @param client - Client to check
|
|
226
|
+
* @returns true if client is IWebUIClient with handleOAuthCallback method
|
|
227
|
+
*/
|
|
228
|
+
export declare function isWebUIClient(client: UIClient): client is IWebUIClient;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { LogLevel } from './types/config';
|
|
2
|
+
|
|
3
|
+
export declare class Logger {
|
|
4
|
+
private prefix;
|
|
5
|
+
private level;
|
|
6
|
+
constructor(prefix: string, level?: LogLevel | 'silent');
|
|
7
|
+
private shouldLog;
|
|
8
|
+
private ts;
|
|
9
|
+
debug(...args: unknown[]): void;
|
|
10
|
+
info(...args: unknown[]): void;
|
|
11
|
+
warn(...args: unknown[]): void;
|
|
12
|
+
error(...args: unknown[]): void;
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { UserInfo } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base64 URL encode a buffer (for PKCE)
|
|
5
|
+
*/
|
|
6
|
+
export declare function base64UrlEncode(buffer: ArrayBuffer): string;
|
|
7
|
+
/**
|
|
8
|
+
* Generate a random code verifier for PKCE
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateCodeVerifier(): string;
|
|
11
|
+
/**
|
|
12
|
+
* Generate code challenge from verifier for PKCE
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Parse JWT token and return payload
|
|
17
|
+
*/
|
|
18
|
+
export declare function parseJwt(token: string): Record<string, unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Extract UserInfo from JWT token
|
|
21
|
+
*/
|
|
22
|
+
export declare function extractUserInfo(token: string): UserInfo;
|
|
23
|
+
export interface OAuthEndpoints {
|
|
24
|
+
authorize: string;
|
|
25
|
+
token: string;
|
|
26
|
+
revoke: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create OAuth endpoints from auth server URL
|
|
30
|
+
*/
|
|
31
|
+
export declare function createOAuthEndpoints(authServerUrl: string): OAuthEndpoints;
|
|
32
|
+
export interface RefreshTokenResponse {
|
|
33
|
+
access_token: string;
|
|
34
|
+
refresh_token?: string;
|
|
35
|
+
id_token?: string;
|
|
36
|
+
expires_in: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Refresh access token using refresh token
|
|
40
|
+
* @param tokenEndpoint - OAuth token endpoint URL
|
|
41
|
+
* @param refreshToken - Current refresh token
|
|
42
|
+
* @param clientId - OAuth client ID
|
|
43
|
+
* @returns New tokens or null if refresh failed
|
|
44
|
+
*/
|
|
45
|
+
export declare function refreshAccessToken(tokenEndpoint: string, refreshToken: string, clientId: string): Promise<RefreshTokenResponse | null>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Browser, OS } from '../../../../setup-modal/src/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Browser configurations with extension store URLs
|
|
5
|
+
*/
|
|
6
|
+
export declare const BROWSER_CONFIGS: Browser[];
|
|
7
|
+
/**
|
|
8
|
+
* Operating system configurations with download URLs
|
|
9
|
+
*/
|
|
10
|
+
export declare const OS_CONFIGS: OS[];
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding module - Framework-agnostic setup modal
|
|
3
|
+
*/
|
|
4
|
+
export { OnboardingModal, type AsyncRequestHandler, type AsyncRequestHandlers, type ModalEvent, type ModalEventMap, type OnboardingModalConfig, } from './modal';
|
|
5
|
+
export { BROWSER_CONFIGS, OS_CONFIGS } from './config';
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { MessageType, RequestMessage, ResponsePayload } from '../../../../setup-modal/src/types';
|
|
2
|
+
|
|
3
|
+
import type * as ModalTypes from '@bodhiapp/setup-modal/types';
|
|
4
|
+
/**
|
|
5
|
+
* Async handler for modal requests
|
|
6
|
+
* Supports both sync and async responses
|
|
7
|
+
*/
|
|
8
|
+
export type AsyncRequestHandler<K extends MessageType> = ((msg: RequestMessage<K>) => Promise<ResponsePayload<K>>) | ((msg: RequestMessage<K>) => ResponsePayload<K>);
|
|
9
|
+
/**
|
|
10
|
+
* Map of message types to async request handlers
|
|
11
|
+
*/
|
|
12
|
+
export type AsyncRequestHandlers = {
|
|
13
|
+
[K in MessageType]?: AsyncRequestHandler<K>;
|
|
14
|
+
};
|
|
15
|
+
export type ModalEvent = 'complete' | 'close' | 'refresh' | 'lna_connect' | 'lna_skip' | 'confirm_server_install' | 'select_connection';
|
|
16
|
+
/**
|
|
17
|
+
* Event payload types for type-safe event handlers
|
|
18
|
+
*/
|
|
19
|
+
export interface ModalEventMap {
|
|
20
|
+
complete: [];
|
|
21
|
+
close: [];
|
|
22
|
+
refresh: [];
|
|
23
|
+
lna_connect: [serverUrl: string];
|
|
24
|
+
lna_skip: [];
|
|
25
|
+
confirm_server_install: [];
|
|
26
|
+
select_connection: [connection: 'lna' | 'extension'];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration options for OnboardingModal
|
|
30
|
+
*/
|
|
31
|
+
export interface OnboardingModalConfig {
|
|
32
|
+
/**
|
|
33
|
+
* Path to modal HTML file relative to extension root
|
|
34
|
+
* Used with chrome.runtime.getURL() in extension context
|
|
35
|
+
* @default 'src/sdk/core/onboarding/modal.html'
|
|
36
|
+
*/
|
|
37
|
+
modalHtmlPath?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Message handlers for iframe requests
|
|
40
|
+
* Required - delegates all business logic to external handlers
|
|
41
|
+
*/
|
|
42
|
+
handlers: AsyncRequestHandlers;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* OnboardingModal manages the setup modal iframe
|
|
46
|
+
* Infrastructure layer only - delegates business logic to handlers
|
|
47
|
+
*/
|
|
48
|
+
export declare class OnboardingModal {
|
|
49
|
+
private overlayElement;
|
|
50
|
+
private iframeElement;
|
|
51
|
+
private isIframeReady;
|
|
52
|
+
private currentSetupState;
|
|
53
|
+
private messageHandler;
|
|
54
|
+
private modalHtmlPath;
|
|
55
|
+
private handlers;
|
|
56
|
+
constructor(config: OnboardingModalConfig);
|
|
57
|
+
/**
|
|
58
|
+
* Show the modal with the given state
|
|
59
|
+
* State building is handled by SetupModalProcessor
|
|
60
|
+
*/
|
|
61
|
+
show(state: ModalTypes.SetupState): void;
|
|
62
|
+
/**
|
|
63
|
+
* Update the modal state
|
|
64
|
+
* Used by SetupModalProcessor to push state updates to the modal
|
|
65
|
+
*/
|
|
66
|
+
updateState(state: ModalTypes.SetupState): void;
|
|
67
|
+
/**
|
|
68
|
+
* Destroy the modal and clean up
|
|
69
|
+
*/
|
|
70
|
+
destroy(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Handle postMessage from iframe
|
|
73
|
+
* Pure routing - delegates to external handlers
|
|
74
|
+
*/
|
|
75
|
+
private handleMessage;
|
|
76
|
+
/**
|
|
77
|
+
* Send current state to modal iframe using event message
|
|
78
|
+
*/
|
|
79
|
+
private sendStateToModal;
|
|
80
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { MessageType, RequestPayload, ResponsePayload, RequestMessage, RequestId } from '../../../../setup-modal/src/types';
|
|
2
|
+
|
|
3
|
+
/** Build fire-and-forget event message */
|
|
4
|
+
export declare function buildEvent<T extends MessageType>(type: T, payload: RequestPayload<T>): {
|
|
5
|
+
kind: "event";
|
|
6
|
+
type: T;
|
|
7
|
+
payload: RequestPayload<T>;
|
|
8
|
+
};
|
|
9
|
+
/** Build response message with requestId correlation */
|
|
10
|
+
export declare function buildResponse<T extends MessageType>(requestId: RequestId, type: T, payload: ResponsePayload<T>): {
|
|
11
|
+
kind: "response";
|
|
12
|
+
type: T;
|
|
13
|
+
requestId: RequestId;
|
|
14
|
+
payload: ResponsePayload<T>;
|
|
15
|
+
};
|
|
16
|
+
/** Build error message */
|
|
17
|
+
export declare function buildError(requestId: RequestId, error: {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
details?: unknown;
|
|
21
|
+
}): {
|
|
22
|
+
kind: "error";
|
|
23
|
+
requestId: RequestId;
|
|
24
|
+
error: {
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
details?: unknown;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/** Type-safe request handler - processes incoming requests and returns response */
|
|
31
|
+
export declare function handleRequest<T extends MessageType>(message: RequestMessage<T>, handlers: Partial<{
|
|
32
|
+
[K in MessageType]: (payload: RequestPayload<K>) => ResponsePayload<K>;
|
|
33
|
+
}>): ReturnType<typeof buildResponse> | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BrowserInfo, OSInfo } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Detects the current browser using UAParser.js
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectBrowser(): BrowserInfo;
|
|
7
|
+
/**
|
|
8
|
+
* Detects the current operating system using UAParser.js
|
|
9
|
+
* Maps all OS variants to simplified supported types
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectOS(): OSInfo;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespaced storage key generator
|
|
3
|
+
*
|
|
4
|
+
* Creates consistent storage keys with prefixes to avoid conflicts between
|
|
5
|
+
* different connection modes and other applications.
|
|
6
|
+
*/
|
|
7
|
+
export interface StorageKeys {
|
|
8
|
+
ACCESS_TOKEN: string;
|
|
9
|
+
REFRESH_TOKEN: string;
|
|
10
|
+
EXPIRES_AT: string;
|
|
11
|
+
CODE_VERIFIER: string;
|
|
12
|
+
STATE: string;
|
|
13
|
+
RESOURCE_SCOPE: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create namespaced storage keys with a given prefix
|
|
17
|
+
*
|
|
18
|
+
* @param prefix - Namespace prefix (e.g., 'bodhi:direct', 'bodhi:web')
|
|
19
|
+
* @returns Storage keys object with namespaced keys
|
|
20
|
+
*/
|
|
21
|
+
export declare function createStorageKeys(prefix: string): StorageKeys;
|
|
22
|
+
/**
|
|
23
|
+
* Standard prefixes for different connection modes
|
|
24
|
+
*/
|
|
25
|
+
export declare const STORAGE_PREFIXES: {
|
|
26
|
+
readonly DIRECT: "bodhi:direct";
|
|
27
|
+
readonly WEB: "bodhi:web";
|
|
28
|
+
readonly EXT: "bodhi:ext";
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* User Preferences Storage Manager
|
|
32
|
+
*
|
|
33
|
+
* Manages localStorage for user preferences including connection mode,
|
|
34
|
+
* server URL, and other client configuration.
|
|
35
|
+
*
|
|
36
|
+
* Storage keys use configurable prefix to namespace all app storage.
|
|
37
|
+
* Defaults to 'bodhijs:' for SDK usage.
|
|
38
|
+
*/
|
|
39
|
+
/**
|
|
40
|
+
* Manager for reading/writing user preferences to localStorage
|
|
41
|
+
*/
|
|
42
|
+
export declare class BodhiClientUserPrefsManager {
|
|
43
|
+
private readonly storagePrefix;
|
|
44
|
+
private readonly STORAGE_KEYS;
|
|
45
|
+
private readonly SERVER_INSTALL_KEY;
|
|
46
|
+
/**
|
|
47
|
+
* @param storagePrefix - Prefix for localStorage keys (default: 'bodhijs:')
|
|
48
|
+
*/
|
|
49
|
+
constructor(storagePrefix?: string);
|
|
50
|
+
/**
|
|
51
|
+
* Get direct connection status (LNA permission state)
|
|
52
|
+
*/
|
|
53
|
+
getDirectStatus(): 'granted' | 'skipped' | 'denied' | null;
|
|
54
|
+
/**
|
|
55
|
+
* Set direct connection status (LNA permission state)
|
|
56
|
+
*/
|
|
57
|
+
setDirectStatus(status: 'granted' | 'skipped' | 'denied' | null): void;
|
|
58
|
+
/**
|
|
59
|
+
* Clear all preferences
|
|
60
|
+
*/
|
|
61
|
+
clear(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Check if server install was confirmed
|
|
64
|
+
* (Separate from connection prefs - stored at server:installed key)
|
|
65
|
+
*/
|
|
66
|
+
isServerInstallConfirmed(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Set server install confirmation
|
|
69
|
+
*/
|
|
70
|
+
setServerInstallConfirmed(confirmed: boolean): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get serialized client state
|
|
73
|
+
*/
|
|
74
|
+
getSerializedClientState<T>(): T | null;
|
|
75
|
+
/**
|
|
76
|
+
* Set serialized client state
|
|
77
|
+
*/
|
|
78
|
+
setSerializedClientState<T>(state: T): void;
|
|
79
|
+
private getStorageValue;
|
|
80
|
+
private setStorageValue;
|
|
81
|
+
}
|