@manonero/chat-client-sdk 0.0.1-beta.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 +2453 -0
- package/dist/ChatClient.d.ts +181 -0
- package/dist/ChatClient.d.ts.map +1 -0
- package/dist/ChatClient.js +246 -0
- package/dist/ChatClient.js.map +1 -0
- package/dist/errors/ChatApiError.d.ts +45 -0
- package/dist/errors/ChatApiError.d.ts.map +1 -0
- package/dist/errors/ChatApiError.js +69 -0
- package/dist/errors/ChatApiError.js.map +1 -0
- package/dist/http/AuthApi.d.ts +26 -0
- package/dist/http/AuthApi.d.ts.map +1 -0
- package/dist/http/AuthApi.js +35 -0
- package/dist/http/AuthApi.js.map +1 -0
- package/dist/http/BotApi.d.ts +43 -0
- package/dist/http/BotApi.d.ts.map +1 -0
- package/dist/http/BotApi.js +60 -0
- package/dist/http/BotApi.js.map +1 -0
- package/dist/http/ConversationApi.d.ts +92 -0
- package/dist/http/ConversationApi.d.ts.map +1 -0
- package/dist/http/ConversationApi.js +128 -0
- package/dist/http/ConversationApi.js.map +1 -0
- package/dist/http/FileApi.d.ts +60 -0
- package/dist/http/FileApi.d.ts.map +1 -0
- package/dist/http/FileApi.js +91 -0
- package/dist/http/FileApi.js.map +1 -0
- package/dist/http/HealthApi.d.ts +28 -0
- package/dist/http/HealthApi.d.ts.map +1 -0
- package/dist/http/HealthApi.js +34 -0
- package/dist/http/HealthApi.js.map +1 -0
- package/dist/http/HttpClient.d.ts +69 -0
- package/dist/http/HttpClient.d.ts.map +1 -0
- package/dist/http/HttpClient.js +244 -0
- package/dist/http/HttpClient.js.map +1 -0
- package/dist/http/MessageApi.d.ts +69 -0
- package/dist/http/MessageApi.d.ts.map +1 -0
- package/dist/http/MessageApi.js +104 -0
- package/dist/http/MessageApi.js.map +1 -0
- package/dist/http/ParticipantApi.d.ts +28 -0
- package/dist/http/ParticipantApi.d.ts.map +1 -0
- package/dist/http/ParticipantApi.js +37 -0
- package/dist/http/ParticipantApi.js.map +1 -0
- package/dist/http/ProxyApi.d.ts +59 -0
- package/dist/http/ProxyApi.d.ts.map +1 -0
- package/dist/http/ProxyApi.js +86 -0
- package/dist/http/ProxyApi.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/realtime/ChatHubClient.d.ts +143 -0
- package/dist/realtime/ChatHubClient.d.ts.map +1 -0
- package/dist/realtime/ChatHubClient.js +365 -0
- package/dist/realtime/ChatHubClient.js.map +1 -0
- package/dist/realtime/NotificationHubClient.d.ts +89 -0
- package/dist/realtime/NotificationHubClient.d.ts.map +1 -0
- package/dist/realtime/NotificationHubClient.js +191 -0
- package/dist/realtime/NotificationHubClient.js.map +1 -0
- package/dist/realtime/ReconnectionManager.d.ts +65 -0
- package/dist/realtime/ReconnectionManager.d.ts.map +1 -0
- package/dist/realtime/ReconnectionManager.js +129 -0
- package/dist/realtime/ReconnectionManager.js.map +1 -0
- package/dist/types/auth.d.ts +30 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/auth.js +3 -0
- package/dist/types/auth.js.map +1 -0
- package/dist/types/block.d.ts +163 -0
- package/dist/types/block.d.ts.map +1 -0
- package/dist/types/block.js +77 -0
- package/dist/types/block.js.map +1 -0
- package/dist/types/bot.d.ts +42 -0
- package/dist/types/bot.d.ts.map +1 -0
- package/dist/types/bot.js +3 -0
- package/dist/types/bot.js.map +1 -0
- package/dist/types/chat-events.d.ts +191 -0
- package/dist/types/chat-events.d.ts.map +1 -0
- package/dist/types/chat-events.js +3 -0
- package/dist/types/chat-events.js.map +1 -0
- package/dist/types/common.d.ts +64 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +3 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/conversation.d.ts +106 -0
- package/dist/types/conversation.d.ts.map +1 -0
- package/dist/types/conversation.js +3 -0
- package/dist/types/conversation.js.map +1 -0
- package/dist/types/file.d.ts +31 -0
- package/dist/types/file.d.ts.map +1 -0
- package/dist/types/file.js +3 -0
- package/dist/types/file.js.map +1 -0
- package/dist/types/message.d.ts +84 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +3 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/notification-events.d.ts +89 -0
- package/dist/types/notification-events.d.ts.map +1 -0
- package/dist/types/notification-events.js +3 -0
- package/dist/types/notification-events.js.map +1 -0
- package/dist/types/participant.d.ts +22 -0
- package/dist/types/participant.d.ts.map +1 -0
- package/dist/types/participant.js +3 -0
- package/dist/types/participant.js.map +1 -0
- package/dist/types/signalr.d.ts +84 -0
- package/dist/types/signalr.d.ts.map +1 -0
- package/dist/types/signalr.js +3 -0
- package/dist/types/signalr.js.map +1 -0
- package/dist/utils/TypedEventEmitter.d.ts +32 -0
- package/dist/utils/TypedEventEmitter.d.ts.map +1 -0
- package/dist/utils/TypedEventEmitter.js +60 -0
- package/dist/utils/TypedEventEmitter.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { LogLevel } from '@microsoft/signalr';
|
|
2
|
+
import { AuthApi } from './http/AuthApi.js';
|
|
3
|
+
import { ParticipantApi } from './http/ParticipantApi.js';
|
|
4
|
+
import { ConversationApi } from './http/ConversationApi.js';
|
|
5
|
+
import { MessageApi } from './http/MessageApi.js';
|
|
6
|
+
import { FileApi } from './http/FileApi.js';
|
|
7
|
+
import { BotApi } from './http/BotApi.js';
|
|
8
|
+
import { ProxyApi } from './http/ProxyApi.js';
|
|
9
|
+
import { HealthApi } from './http/HealthApi.js';
|
|
10
|
+
import { ChatHubClient } from './realtime/ChatHubClient.js';
|
|
11
|
+
import { NotificationHubClient } from './realtime/NotificationHubClient.js';
|
|
12
|
+
import type { AuthUserInfo } from './types/auth.js';
|
|
13
|
+
export interface ChatClientSignalrOptions {
|
|
14
|
+
/** Minimum log level for SignalR internal logging (default: Warning) */
|
|
15
|
+
logLevel?: LogLevel;
|
|
16
|
+
}
|
|
17
|
+
export interface ChatClientOptions {
|
|
18
|
+
/** Base URL of the API server, e.g. "https://chat-api.example.com" */
|
|
19
|
+
baseUrl: string;
|
|
20
|
+
/**
|
|
21
|
+
* Initial JWT token (if already authenticated).
|
|
22
|
+
* Can be updated later via setToken().
|
|
23
|
+
*/
|
|
24
|
+
token?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Optional external token provider function.
|
|
27
|
+
*
|
|
28
|
+
* Resolution order on every request / connect:
|
|
29
|
+
* 1. If `tokenProvider` is set AND returns a non-empty string, that value
|
|
30
|
+
* is used (so external rotation systems are honored on each call).
|
|
31
|
+
* 2. Otherwise the internal token (constructor `token`, `setToken()`, or
|
|
32
|
+
* auto-set after a successful login) is used.
|
|
33
|
+
* 3. Otherwise null (no Authorization header sent).
|
|
34
|
+
*
|
|
35
|
+
* Note: this is reversed from the previous beta — previously a one-time
|
|
36
|
+
* setToken() would shadow the provider permanently. Now the provider always
|
|
37
|
+
* wins when it returns a value. Use `clearToken()` if you want to make sure
|
|
38
|
+
* the provider takes over after using setToken().
|
|
39
|
+
*/
|
|
40
|
+
tokenProvider?: () => string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Per-request HTTP timeout in milliseconds. Default 30000 (30s).
|
|
43
|
+
* Pass `null` to disable the timeout — useful when uploading large files.
|
|
44
|
+
*/
|
|
45
|
+
requestTimeoutMs?: number | null;
|
|
46
|
+
/** Options for SignalR hub connections */
|
|
47
|
+
signalrOptions?: ChatClientSignalrOptions;
|
|
48
|
+
}
|
|
49
|
+
export interface ChatClientRealtime {
|
|
50
|
+
/** ChatHub real-time client for conversation-level events */
|
|
51
|
+
readonly chat: ChatHubClient;
|
|
52
|
+
/** NotificationHub real-time client for user-level notifications */
|
|
53
|
+
readonly notifications: NotificationHubClient;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Main SDK facade.
|
|
57
|
+
*
|
|
58
|
+
* Integrates all HTTP API modules and SignalR hub clients into a single
|
|
59
|
+
* ergonomic entry point. Manages a shared JWT token that is automatically
|
|
60
|
+
* propagated to all HTTP requests and new SignalR connections.
|
|
61
|
+
*
|
|
62
|
+
* Usage:
|
|
63
|
+
* ```ts
|
|
64
|
+
* const client = new ChatClient({ baseUrl: 'https://chat-api.example.com' });
|
|
65
|
+
*
|
|
66
|
+
* const auth = await client.auth.loginWithGoogle(idToken);
|
|
67
|
+
* // token and currentUser are automatically set after login
|
|
68
|
+
*
|
|
69
|
+
* await client.realtime.notifications.connect();
|
|
70
|
+
* await client.realtime.chat.connect();
|
|
71
|
+
*
|
|
72
|
+
* client.realtime.chat.on('messageReceived', (msg) => console.log(msg));
|
|
73
|
+
* await client.realtime.chat.joinConversation('conv-id');
|
|
74
|
+
*
|
|
75
|
+
* await client.disconnect(); // Disconnect all hubs
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* Note on token propagation for SignalR:
|
|
79
|
+
* Calling setToken() updates HTTP requests immediately, but active SignalR
|
|
80
|
+
* connections must be reconnected (disconnect() → connect()) for the new
|
|
81
|
+
* token to take effect.
|
|
82
|
+
*/
|
|
83
|
+
export declare class ChatClient {
|
|
84
|
+
/**
|
|
85
|
+
* Internally held JWT token (set via constructor `token`, `setToken()`, or
|
|
86
|
+
* after a successful login).
|
|
87
|
+
*
|
|
88
|
+
* Acts as the fallback when no `tokenProvider` is configured, or when the
|
|
89
|
+
* configured `tokenProvider` returns null. The external `tokenProvider`
|
|
90
|
+
* always wins when it returns a non-empty value — see
|
|
91
|
+
* {@link ChatClientOptions.tokenProvider}.
|
|
92
|
+
*/
|
|
93
|
+
private _token;
|
|
94
|
+
/**
|
|
95
|
+
* Combined internal token provider. Returns _token if set, otherwise falls
|
|
96
|
+
* back to any externally supplied tokenProvider, otherwise null.
|
|
97
|
+
*/
|
|
98
|
+
private readonly _internalTokenProvider;
|
|
99
|
+
/** Authentication endpoints */
|
|
100
|
+
readonly auth: AuthApi;
|
|
101
|
+
/** Participant management */
|
|
102
|
+
readonly participants: ParticipantApi;
|
|
103
|
+
/** Conversation management */
|
|
104
|
+
readonly conversations: ConversationApi;
|
|
105
|
+
/** Message operations */
|
|
106
|
+
readonly messages: MessageApi;
|
|
107
|
+
/** File upload / download */
|
|
108
|
+
readonly files: FileApi;
|
|
109
|
+
/** Bot management */
|
|
110
|
+
readonly bots: BotApi;
|
|
111
|
+
/** Dynamic backend proxy */
|
|
112
|
+
readonly proxy: ProxyApi;
|
|
113
|
+
/** Health check endpoints */
|
|
114
|
+
readonly health: HealthApi;
|
|
115
|
+
/** SignalR hub clients */
|
|
116
|
+
readonly realtime: ChatClientRealtime;
|
|
117
|
+
private _currentUser;
|
|
118
|
+
/** The authenticated user populated automatically after a successful login. */
|
|
119
|
+
get currentUser(): AuthUserInfo | null;
|
|
120
|
+
constructor(options: ChatClientOptions);
|
|
121
|
+
/**
|
|
122
|
+
* Update the JWT token.
|
|
123
|
+
*
|
|
124
|
+
* Effect on requests:
|
|
125
|
+
* - HTTP: takes effect on the very next request.
|
|
126
|
+
* - SignalR: existing active connections keep using the token they were
|
|
127
|
+
* opened with. To apply the new token immediately to active hubs, call
|
|
128
|
+
* `refreshConnections()` after `setToken()`.
|
|
129
|
+
*
|
|
130
|
+
* Pass `null` to clear the internally held token (same as `clearToken()`):
|
|
131
|
+
* both `_token` and `currentUser` are cleared so the SDK no longer reports
|
|
132
|
+
* stale identity. If a `tokenProvider` is configured and still returns a
|
|
133
|
+
* value, it will continue to be used regardless of this call.
|
|
134
|
+
*/
|
|
135
|
+
setToken(token: string | null): void;
|
|
136
|
+
/**
|
|
137
|
+
* Clear the internally held JWT token and authenticated user.
|
|
138
|
+
*
|
|
139
|
+
* After this, the configured `tokenProvider` (if any) becomes the only
|
|
140
|
+
* source of tokens. Use `logout()` instead when you also want to disconnect
|
|
141
|
+
* SignalR hubs.
|
|
142
|
+
*/
|
|
143
|
+
clearToken(): void;
|
|
144
|
+
/**
|
|
145
|
+
* Disconnect any active SignalR hub and reconnect it with the latest token.
|
|
146
|
+
*
|
|
147
|
+
* Useful right after `setToken()` to propagate the new token to live hubs.
|
|
148
|
+
* Hubs that are not currently connected are left untouched.
|
|
149
|
+
*
|
|
150
|
+
* Re-joins of conversations are NOT performed automatically here —
|
|
151
|
+
* `disconnect()` clears that local tracking by design.
|
|
152
|
+
* The application is responsible for re-issuing those after a manual refresh
|
|
153
|
+
* (or for using `ReconnectionManager` for transparent recovery).
|
|
154
|
+
*/
|
|
155
|
+
refreshConnections(): Promise<void>;
|
|
156
|
+
/**
|
|
157
|
+
* Log the current user out: clear the internal token + currentUser and
|
|
158
|
+
* disconnect both SignalR hubs.
|
|
159
|
+
*
|
|
160
|
+
* Note: there is no server-side logout endpoint — this only clears local
|
|
161
|
+
* SDK state. If a `tokenProvider` is configured and still returns a token,
|
|
162
|
+
* subsequent requests can authenticate again with that token.
|
|
163
|
+
*/
|
|
164
|
+
logout(): Promise<void>;
|
|
165
|
+
/**
|
|
166
|
+
* Disconnect all SignalR hubs (ChatHub + NotificationHub).
|
|
167
|
+
*
|
|
168
|
+
* Resolves after both hubs have finished disconnecting. Individual hub
|
|
169
|
+
* disconnect failures do not prevent the other hub from disconnecting.
|
|
170
|
+
*
|
|
171
|
+
* Both hubs set their `intentionallyClosed` flag, so a `ReconnectionManager`
|
|
172
|
+
* attached to them will skip auto-reconnect for the resulting close.
|
|
173
|
+
*/
|
|
174
|
+
disconnect(): Promise<void>;
|
|
175
|
+
/**
|
|
176
|
+
* Called automatically after every successful login.
|
|
177
|
+
* Sets the token and populates currentUser from the auth response.
|
|
178
|
+
*/
|
|
179
|
+
private _onLoginSuccess;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=ChatClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatClient.d.ts","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// ChatClient.ts — Main SDK facade
|
|
2
|
+
import { HubConnectionState, LogLevel } from '@microsoft/signalr';
|
|
3
|
+
import { HttpClient } from './http/HttpClient.js';
|
|
4
|
+
import { AuthApi } from './http/AuthApi.js';
|
|
5
|
+
import { ParticipantApi } from './http/ParticipantApi.js';
|
|
6
|
+
import { ConversationApi } from './http/ConversationApi.js';
|
|
7
|
+
import { MessageApi } from './http/MessageApi.js';
|
|
8
|
+
import { FileApi } from './http/FileApi.js';
|
|
9
|
+
import { BotApi } from './http/BotApi.js';
|
|
10
|
+
import { ProxyApi } from './http/ProxyApi.js';
|
|
11
|
+
import { HealthApi } from './http/HealthApi.js';
|
|
12
|
+
import { ChatHubClient } from './realtime/ChatHubClient.js';
|
|
13
|
+
import { NotificationHubClient } from './realtime/NotificationHubClient.js';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// AuthApi subclass that auto-sets token + currentUser on login success
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Internal subclass of AuthApi.
|
|
19
|
+
* Overrides each login method to call onSuccess with the AuthResponse,
|
|
20
|
+
* allowing ChatClient to update its token and currentUser automatically.
|
|
21
|
+
*/
|
|
22
|
+
class InterceptingAuthApi extends AuthApi {
|
|
23
|
+
constructor(http, onSuccess) {
|
|
24
|
+
super(http);
|
|
25
|
+
this._onSuccess = onSuccess;
|
|
26
|
+
}
|
|
27
|
+
login(provider, body) {
|
|
28
|
+
return super.login(provider, body).then((res) => {
|
|
29
|
+
this._onSuccess(res);
|
|
30
|
+
return res;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
loginWithGoogle(idToken) {
|
|
34
|
+
return super.loginWithGoogle(idToken).then((res) => {
|
|
35
|
+
this._onSuccess(res);
|
|
36
|
+
return res;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
loginWithDsAccount(token) {
|
|
40
|
+
return super.loginWithDsAccount(token).then((res) => {
|
|
41
|
+
this._onSuccess(res);
|
|
42
|
+
return res;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
loginWithDev(username, password) {
|
|
46
|
+
return super.loginWithDev(username, password).then((res) => {
|
|
47
|
+
this._onSuccess(res);
|
|
48
|
+
return res;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// ChatClient
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
/**
|
|
56
|
+
* Main SDK facade.
|
|
57
|
+
*
|
|
58
|
+
* Integrates all HTTP API modules and SignalR hub clients into a single
|
|
59
|
+
* ergonomic entry point. Manages a shared JWT token that is automatically
|
|
60
|
+
* propagated to all HTTP requests and new SignalR connections.
|
|
61
|
+
*
|
|
62
|
+
* Usage:
|
|
63
|
+
* ```ts
|
|
64
|
+
* const client = new ChatClient({ baseUrl: 'https://chat-api.example.com' });
|
|
65
|
+
*
|
|
66
|
+
* const auth = await client.auth.loginWithGoogle(idToken);
|
|
67
|
+
* // token and currentUser are automatically set after login
|
|
68
|
+
*
|
|
69
|
+
* await client.realtime.notifications.connect();
|
|
70
|
+
* await client.realtime.chat.connect();
|
|
71
|
+
*
|
|
72
|
+
* client.realtime.chat.on('messageReceived', (msg) => console.log(msg));
|
|
73
|
+
* await client.realtime.chat.joinConversation('conv-id');
|
|
74
|
+
*
|
|
75
|
+
* await client.disconnect(); // Disconnect all hubs
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* Note on token propagation for SignalR:
|
|
79
|
+
* Calling setToken() updates HTTP requests immediately, but active SignalR
|
|
80
|
+
* connections must be reconnected (disconnect() → connect()) for the new
|
|
81
|
+
* token to take effect.
|
|
82
|
+
*/
|
|
83
|
+
export class ChatClient {
|
|
84
|
+
/** The authenticated user populated automatically after a successful login. */
|
|
85
|
+
get currentUser() {
|
|
86
|
+
return this._currentUser;
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Constructor
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
constructor(options) {
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
// State
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
this._currentUser = null;
|
|
96
|
+
this._token = options.token ?? null;
|
|
97
|
+
// Build the combined token provider — see ChatClientOptions.tokenProvider
|
|
98
|
+
// for the rationale. The external provider takes priority when it returns
|
|
99
|
+
// a non-empty value so refresh-token rotation systems keep working even
|
|
100
|
+
// after setToken() has been called.
|
|
101
|
+
const externalProvider = options.tokenProvider;
|
|
102
|
+
this._internalTokenProvider = () => {
|
|
103
|
+
if (externalProvider) {
|
|
104
|
+
const fromProvider = externalProvider();
|
|
105
|
+
if (fromProvider)
|
|
106
|
+
return fromProvider;
|
|
107
|
+
}
|
|
108
|
+
return this._token;
|
|
109
|
+
};
|
|
110
|
+
// Shared HTTP client used by all REST API modules
|
|
111
|
+
const http = new HttpClient({
|
|
112
|
+
baseUrl: options.baseUrl,
|
|
113
|
+
tokenProvider: this._internalTokenProvider,
|
|
114
|
+
...(options.requestTimeoutMs !== undefined
|
|
115
|
+
? { requestTimeoutMs: options.requestTimeoutMs }
|
|
116
|
+
: {}),
|
|
117
|
+
});
|
|
118
|
+
// Instantiate REST API modules
|
|
119
|
+
this.participants = new ParticipantApi(http);
|
|
120
|
+
this.conversations = new ConversationApi(http);
|
|
121
|
+
this.messages = new MessageApi(http);
|
|
122
|
+
this.files = new FileApi(http);
|
|
123
|
+
this.bots = new BotApi(http);
|
|
124
|
+
this.proxy = new ProxyApi(http);
|
|
125
|
+
this.health = new HealthApi(http);
|
|
126
|
+
// AuthApi is wrapped in InterceptingAuthApi to auto-set token + currentUser
|
|
127
|
+
this.auth = new InterceptingAuthApi(http, (res) => this._onLoginSuccess(res));
|
|
128
|
+
// Build SignalR hub URLs from baseUrl (strip trailing slash already done by HttpClient)
|
|
129
|
+
const baseUrl = http.baseUrl; // already has trailing slash stripped
|
|
130
|
+
const { logLevel } = options.signalrOptions ?? {};
|
|
131
|
+
const chatHubOptions = {
|
|
132
|
+
hubUrl: `${baseUrl}/hubs/chat`,
|
|
133
|
+
tokenProvider: this._internalTokenProvider,
|
|
134
|
+
...(logLevel !== undefined ? { logLevel } : {}),
|
|
135
|
+
};
|
|
136
|
+
const notificationHubOptions = {
|
|
137
|
+
hubUrl: `${baseUrl}/hubs/notifications`,
|
|
138
|
+
tokenProvider: this._internalTokenProvider,
|
|
139
|
+
...(logLevel !== undefined ? { logLevel } : {}),
|
|
140
|
+
};
|
|
141
|
+
this.realtime = {
|
|
142
|
+
chat: new ChatHubClient(chatHubOptions),
|
|
143
|
+
notifications: new NotificationHubClient(notificationHubOptions),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Public methods
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
/**
|
|
150
|
+
* Update the JWT token.
|
|
151
|
+
*
|
|
152
|
+
* Effect on requests:
|
|
153
|
+
* - HTTP: takes effect on the very next request.
|
|
154
|
+
* - SignalR: existing active connections keep using the token they were
|
|
155
|
+
* opened with. To apply the new token immediately to active hubs, call
|
|
156
|
+
* `refreshConnections()` after `setToken()`.
|
|
157
|
+
*
|
|
158
|
+
* Pass `null` to clear the internally held token (same as `clearToken()`):
|
|
159
|
+
* both `_token` and `currentUser` are cleared so the SDK no longer reports
|
|
160
|
+
* stale identity. If a `tokenProvider` is configured and still returns a
|
|
161
|
+
* value, it will continue to be used regardless of this call.
|
|
162
|
+
*/
|
|
163
|
+
setToken(token) {
|
|
164
|
+
this._token = token;
|
|
165
|
+
if (token === null) {
|
|
166
|
+
this._currentUser = null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Clear the internally held JWT token and authenticated user.
|
|
171
|
+
*
|
|
172
|
+
* After this, the configured `tokenProvider` (if any) becomes the only
|
|
173
|
+
* source of tokens. Use `logout()` instead when you also want to disconnect
|
|
174
|
+
* SignalR hubs.
|
|
175
|
+
*/
|
|
176
|
+
clearToken() {
|
|
177
|
+
this._token = null;
|
|
178
|
+
this._currentUser = null;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Disconnect any active SignalR hub and reconnect it with the latest token.
|
|
182
|
+
*
|
|
183
|
+
* Useful right after `setToken()` to propagate the new token to live hubs.
|
|
184
|
+
* Hubs that are not currently connected are left untouched.
|
|
185
|
+
*
|
|
186
|
+
* Re-joins of conversations are NOT performed automatically here —
|
|
187
|
+
* `disconnect()` clears that local tracking by design.
|
|
188
|
+
* The application is responsible for re-issuing those after a manual refresh
|
|
189
|
+
* (or for using `ReconnectionManager` for transparent recovery).
|
|
190
|
+
*/
|
|
191
|
+
async refreshConnections() {
|
|
192
|
+
const tasks = [];
|
|
193
|
+
if (this.realtime.chat.state === HubConnectionState.Connected) {
|
|
194
|
+
tasks.push((async () => {
|
|
195
|
+
await this.realtime.chat.disconnect();
|
|
196
|
+
await this.realtime.chat.connect();
|
|
197
|
+
})());
|
|
198
|
+
}
|
|
199
|
+
if (this.realtime.notifications.state === HubConnectionState.Connected) {
|
|
200
|
+
tasks.push((async () => {
|
|
201
|
+
await this.realtime.notifications.disconnect();
|
|
202
|
+
await this.realtime.notifications.connect();
|
|
203
|
+
})());
|
|
204
|
+
}
|
|
205
|
+
await Promise.all(tasks);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Log the current user out: clear the internal token + currentUser and
|
|
209
|
+
* disconnect both SignalR hubs.
|
|
210
|
+
*
|
|
211
|
+
* Note: there is no server-side logout endpoint — this only clears local
|
|
212
|
+
* SDK state. If a `tokenProvider` is configured and still returns a token,
|
|
213
|
+
* subsequent requests can authenticate again with that token.
|
|
214
|
+
*/
|
|
215
|
+
async logout() {
|
|
216
|
+
this.clearToken();
|
|
217
|
+
await this.disconnect();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Disconnect all SignalR hubs (ChatHub + NotificationHub).
|
|
221
|
+
*
|
|
222
|
+
* Resolves after both hubs have finished disconnecting. Individual hub
|
|
223
|
+
* disconnect failures do not prevent the other hub from disconnecting.
|
|
224
|
+
*
|
|
225
|
+
* Both hubs set their `intentionallyClosed` flag, so a `ReconnectionManager`
|
|
226
|
+
* attached to them will skip auto-reconnect for the resulting close.
|
|
227
|
+
*/
|
|
228
|
+
async disconnect() {
|
|
229
|
+
await Promise.allSettled([
|
|
230
|
+
this.realtime.chat.disconnect(),
|
|
231
|
+
this.realtime.notifications.disconnect(),
|
|
232
|
+
]);
|
|
233
|
+
}
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Private helpers
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
/**
|
|
238
|
+
* Called automatically after every successful login.
|
|
239
|
+
* Sets the token and populates currentUser from the auth response.
|
|
240
|
+
*/
|
|
241
|
+
_onLoginSuccess(response) {
|
|
242
|
+
this._token = response.token;
|
|
243
|
+
this._currentUser = response.user;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=ChatClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatClient.js","sourceRoot":"","sources":["../src/ChatClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ProblemDetails, ProblemError } from '../types/common.js';
|
|
2
|
+
/**
|
|
3
|
+
* Custom error thrown for all HTTP API failures.
|
|
4
|
+
*
|
|
5
|
+
* Handles two error formats from the server:
|
|
6
|
+
* 1. RFC 7807 full: { status, title, detail?, errors?, traceId? } — standard REST endpoints
|
|
7
|
+
* 2. Proxy error simple: { detail } — /api/proxy/* endpoints
|
|
8
|
+
*/
|
|
9
|
+
export declare class ChatApiError extends Error {
|
|
10
|
+
readonly status: number;
|
|
11
|
+
readonly title: string;
|
|
12
|
+
readonly detail: string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* RFC 7807 problem `type` URI (e.g. "https://tools.ietf.org/html/rfc9110#section-15.5.1").
|
|
15
|
+
* Set when the server emits a typed problem document; `undefined` for proxy errors
|
|
16
|
+
* and synthetic SDK errors (timeouts, network failures, parse errors).
|
|
17
|
+
*/
|
|
18
|
+
readonly type: string | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Array of structured error details returned by handler endpoints (ErrorOr path).
|
|
21
|
+
* Each entry has `code`, `description`, and `type` (ErrorType enum value).
|
|
22
|
+
* `undefined` for middleware/filter errors and proxy errors.
|
|
23
|
+
*/
|
|
24
|
+
readonly errors: ProblemError[] | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* W3C trace ID for log correlation.
|
|
27
|
+
* Added automatically by the framework; `undefined` for synthetic SDK errors.
|
|
28
|
+
*/
|
|
29
|
+
readonly traceId: string | undefined;
|
|
30
|
+
constructor(status: number, title: string, detail?: string, type?: string, errors?: ProblemError[], traceId?: string);
|
|
31
|
+
/**
|
|
32
|
+
* Parse a ChatApiError from a failed HTTP response.
|
|
33
|
+
*
|
|
34
|
+
* Handles three body shapes:
|
|
35
|
+
* - RFC 7807 JSON (`{ status, title, detail?, errors?, traceId? }`) — standard REST endpoints (spec §3).
|
|
36
|
+
* - Proxy JSON (`{ detail }`) — `/api/proxy/*` (spec §10.1).
|
|
37
|
+
* - Plain text (e.g. `"Unhealthy"`) — `/health/*` (spec §11), surfaced via `detail`.
|
|
38
|
+
*
|
|
39
|
+
* Falls back to `statusText` if the body cannot be read or is empty.
|
|
40
|
+
*/
|
|
41
|
+
static fromResponse(response: Response): Promise<ChatApiError>;
|
|
42
|
+
/** Convenience: create from a ProblemDetails object directly */
|
|
43
|
+
static fromProblemDetails(pd: ProblemDetails): ChatApiError;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=ChatApiError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatApiError.d.ts","sourceRoot":"","sources":["../../src/errors/ChatApiError.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvE;;;;;;GAMG;AACH,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,SAAS,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,YAAY,EAAE,EACvB,OAAO,CAAC,EAAE,MAAM;IAclB;;;;;;;;;OASG;WACU,YAAY,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IA4CpE,gEAAgE;IAChE,MAAM,CAAC,kBAAkB,CAAC,EAAE,EAAE,cAAc,GAAG,YAAY;CAG5D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// ChatApiError.ts — Custom error class (RFC 7807 compatible)
|
|
2
|
+
/**
|
|
3
|
+
* Custom error thrown for all HTTP API failures.
|
|
4
|
+
*
|
|
5
|
+
* Handles two error formats from the server:
|
|
6
|
+
* 1. RFC 7807 full: { status, title, detail?, errors?, traceId? } — standard REST endpoints
|
|
7
|
+
* 2. Proxy error simple: { detail } — /api/proxy/* endpoints
|
|
8
|
+
*/
|
|
9
|
+
export class ChatApiError extends Error {
|
|
10
|
+
constructor(status, title, detail, type, errors, traceId) {
|
|
11
|
+
super(detail ?? title);
|
|
12
|
+
this.name = 'ChatApiError';
|
|
13
|
+
this.status = status;
|
|
14
|
+
this.title = title;
|
|
15
|
+
this.detail = detail;
|
|
16
|
+
this.type = type;
|
|
17
|
+
this.errors = errors;
|
|
18
|
+
this.traceId = traceId;
|
|
19
|
+
// Maintain proper prototype chain for instanceof checks
|
|
20
|
+
Object.setPrototypeOf(this, ChatApiError.prototype);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse a ChatApiError from a failed HTTP response.
|
|
24
|
+
*
|
|
25
|
+
* Handles three body shapes:
|
|
26
|
+
* - RFC 7807 JSON (`{ status, title, detail?, errors?, traceId? }`) — standard REST endpoints (spec §3).
|
|
27
|
+
* - Proxy JSON (`{ detail }`) — `/api/proxy/*` (spec §10.1).
|
|
28
|
+
* - Plain text (e.g. `"Unhealthy"`) — `/health/*` (spec §11), surfaced via `detail`.
|
|
29
|
+
*
|
|
30
|
+
* Falls back to `statusText` if the body cannot be read or is empty.
|
|
31
|
+
*/
|
|
32
|
+
static async fromResponse(response) {
|
|
33
|
+
const rawText = await response.text().catch(() => '');
|
|
34
|
+
const text = rawText.trim();
|
|
35
|
+
if (!text) {
|
|
36
|
+
return new ChatApiError(response.status, response.statusText);
|
|
37
|
+
}
|
|
38
|
+
// Try JSON first regardless of Content-Type — some servers mislabel JSON
|
|
39
|
+
// as text/plain. If parsing fails, treat as plain text.
|
|
40
|
+
let body;
|
|
41
|
+
try {
|
|
42
|
+
body = JSON.parse(rawText);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Plain-text body (e.g. /health/* returns "Healthy"/"Degraded"/"Unhealthy").
|
|
46
|
+
return new ChatApiError(response.status, response.statusText, text);
|
|
47
|
+
}
|
|
48
|
+
if (body !== null && typeof body === 'object') {
|
|
49
|
+
const obj = body;
|
|
50
|
+
// RFC 7807 full format: { type?, status, title, detail?, errors?, traceId? }
|
|
51
|
+
if (typeof obj['title'] === 'string') {
|
|
52
|
+
const errors = Array.isArray(obj['errors'])
|
|
53
|
+
? obj['errors']
|
|
54
|
+
: undefined;
|
|
55
|
+
return new ChatApiError(typeof obj['status'] === 'number' ? obj['status'] : response.status, obj['title'], typeof obj['detail'] === 'string' ? obj['detail'] : undefined, typeof obj['type'] === 'string' ? obj['type'] : undefined, errors, typeof obj['traceId'] === 'string' ? obj['traceId'] : undefined);
|
|
56
|
+
}
|
|
57
|
+
// Proxy error simple format: { detail }
|
|
58
|
+
if (typeof obj['detail'] === 'string') {
|
|
59
|
+
return new ChatApiError(response.status, 'Proxy Error', obj['detail']);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return new ChatApiError(response.status, response.statusText);
|
|
63
|
+
}
|
|
64
|
+
/** Convenience: create from a ProblemDetails object directly */
|
|
65
|
+
static fromProblemDetails(pd) {
|
|
66
|
+
return new ChatApiError(pd.status, pd.title, pd.detail, pd.type, pd.errors, pd.traceId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=ChatApiError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatApiError.js","sourceRoot":"","sources":["../../src/errors/ChatApiError.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { HttpClient } from './HttpClient.js';
|
|
2
|
+
import type { AuthResponse, LoginRequest } from '../types/auth.js';
|
|
3
|
+
/**
|
|
4
|
+
* Auth API client.
|
|
5
|
+
* All endpoints are public (no JWT required).
|
|
6
|
+
*/
|
|
7
|
+
export declare class AuthApi {
|
|
8
|
+
private readonly http;
|
|
9
|
+
constructor(http: HttpClient);
|
|
10
|
+
/**
|
|
11
|
+
* Generic login — POST /api/auth/{provider}
|
|
12
|
+
* Use this when you need a runtime-determined provider name.
|
|
13
|
+
*/
|
|
14
|
+
login(provider: string, body: LoginRequest): Promise<AuthResponse>;
|
|
15
|
+
/** POST /api/auth/google */
|
|
16
|
+
loginWithGoogle(idToken: string): Promise<AuthResponse>;
|
|
17
|
+
/** POST /api/auth/dsaccount */
|
|
18
|
+
loginWithDsAccount(token: string): Promise<AuthResponse>;
|
|
19
|
+
/**
|
|
20
|
+
* POST /api/auth/dev
|
|
21
|
+
* Only available in development environments.
|
|
22
|
+
* Grants role=dev in JWT, unlocking bot management endpoints.
|
|
23
|
+
*/
|
|
24
|
+
loginWithDev(username: string, password: string): Promise<AuthResponse>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AuthApi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthApi.d.ts","sourceRoot":"","sources":["../../src/http/AuthApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEnE;;;GAGG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;OAGG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IAIlE,4BAA4B;IAC5B,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIvD,+BAA+B;IAC/B,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIxD;;;;OAIG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAGxE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// AuthApi.ts — Authentication endpoints
|
|
2
|
+
import { HttpClient } from './HttpClient.js';
|
|
3
|
+
/**
|
|
4
|
+
* Auth API client.
|
|
5
|
+
* All endpoints are public (no JWT required).
|
|
6
|
+
*/
|
|
7
|
+
export class AuthApi {
|
|
8
|
+
constructor(http) {
|
|
9
|
+
this.http = http;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generic login — POST /api/auth/{provider}
|
|
13
|
+
* Use this when you need a runtime-determined provider name.
|
|
14
|
+
*/
|
|
15
|
+
login(provider, body) {
|
|
16
|
+
return this.http.post(`/api/auth/${encodeURIComponent(provider)}`, body);
|
|
17
|
+
}
|
|
18
|
+
/** POST /api/auth/google */
|
|
19
|
+
loginWithGoogle(idToken) {
|
|
20
|
+
return this.http.post('/api/auth/google', { idToken });
|
|
21
|
+
}
|
|
22
|
+
/** POST /api/auth/dsaccount */
|
|
23
|
+
loginWithDsAccount(token) {
|
|
24
|
+
return this.http.post('/api/auth/dsaccount', { token });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* POST /api/auth/dev
|
|
28
|
+
* Only available in development environments.
|
|
29
|
+
* Grants role=dev in JWT, unlocking bot management endpoints.
|
|
30
|
+
*/
|
|
31
|
+
loginWithDev(username, password) {
|
|
32
|
+
return this.http.post('/api/auth/dev', { username, password });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=AuthApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthApi.js","sourceRoot":"","sources":["../../src/http/AuthApi.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;;GAGG;AACH,MAAM,OAAO,OAAO;IAGlB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,QAAgB,EAAE,IAAkB;QACxC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAe,aAAa,kBAAkB,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzF,CAAC;IAED,4BAA4B;IAC5B,eAAe,CAAC,OAAe;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAe,kBAAkB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,+BAA+B;IAC/B,kBAAkB,CAAC,KAAa;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAe,qBAAqB,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACxE,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,QAAgB,EAAE,QAAgB;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAe,eAAe,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/E,CAAC;CACF"}
|