@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.
Files changed (110) hide show
  1. package/README.md +2453 -0
  2. package/dist/ChatClient.d.ts +181 -0
  3. package/dist/ChatClient.d.ts.map +1 -0
  4. package/dist/ChatClient.js +246 -0
  5. package/dist/ChatClient.js.map +1 -0
  6. package/dist/errors/ChatApiError.d.ts +45 -0
  7. package/dist/errors/ChatApiError.d.ts.map +1 -0
  8. package/dist/errors/ChatApiError.js +69 -0
  9. package/dist/errors/ChatApiError.js.map +1 -0
  10. package/dist/http/AuthApi.d.ts +26 -0
  11. package/dist/http/AuthApi.d.ts.map +1 -0
  12. package/dist/http/AuthApi.js +35 -0
  13. package/dist/http/AuthApi.js.map +1 -0
  14. package/dist/http/BotApi.d.ts +43 -0
  15. package/dist/http/BotApi.d.ts.map +1 -0
  16. package/dist/http/BotApi.js +60 -0
  17. package/dist/http/BotApi.js.map +1 -0
  18. package/dist/http/ConversationApi.d.ts +92 -0
  19. package/dist/http/ConversationApi.d.ts.map +1 -0
  20. package/dist/http/ConversationApi.js +128 -0
  21. package/dist/http/ConversationApi.js.map +1 -0
  22. package/dist/http/FileApi.d.ts +60 -0
  23. package/dist/http/FileApi.d.ts.map +1 -0
  24. package/dist/http/FileApi.js +91 -0
  25. package/dist/http/FileApi.js.map +1 -0
  26. package/dist/http/HealthApi.d.ts +28 -0
  27. package/dist/http/HealthApi.d.ts.map +1 -0
  28. package/dist/http/HealthApi.js +34 -0
  29. package/dist/http/HealthApi.js.map +1 -0
  30. package/dist/http/HttpClient.d.ts +69 -0
  31. package/dist/http/HttpClient.d.ts.map +1 -0
  32. package/dist/http/HttpClient.js +244 -0
  33. package/dist/http/HttpClient.js.map +1 -0
  34. package/dist/http/MessageApi.d.ts +69 -0
  35. package/dist/http/MessageApi.d.ts.map +1 -0
  36. package/dist/http/MessageApi.js +104 -0
  37. package/dist/http/MessageApi.js.map +1 -0
  38. package/dist/http/ParticipantApi.d.ts +28 -0
  39. package/dist/http/ParticipantApi.d.ts.map +1 -0
  40. package/dist/http/ParticipantApi.js +37 -0
  41. package/dist/http/ParticipantApi.js.map +1 -0
  42. package/dist/http/ProxyApi.d.ts +59 -0
  43. package/dist/http/ProxyApi.d.ts.map +1 -0
  44. package/dist/http/ProxyApi.js +86 -0
  45. package/dist/http/ProxyApi.js.map +1 -0
  46. package/dist/index.d.ts +26 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +18 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/realtime/ChatHubClient.d.ts +143 -0
  51. package/dist/realtime/ChatHubClient.d.ts.map +1 -0
  52. package/dist/realtime/ChatHubClient.js +365 -0
  53. package/dist/realtime/ChatHubClient.js.map +1 -0
  54. package/dist/realtime/NotificationHubClient.d.ts +89 -0
  55. package/dist/realtime/NotificationHubClient.d.ts.map +1 -0
  56. package/dist/realtime/NotificationHubClient.js +191 -0
  57. package/dist/realtime/NotificationHubClient.js.map +1 -0
  58. package/dist/realtime/ReconnectionManager.d.ts +65 -0
  59. package/dist/realtime/ReconnectionManager.d.ts.map +1 -0
  60. package/dist/realtime/ReconnectionManager.js +129 -0
  61. package/dist/realtime/ReconnectionManager.js.map +1 -0
  62. package/dist/types/auth.d.ts +30 -0
  63. package/dist/types/auth.d.ts.map +1 -0
  64. package/dist/types/auth.js +3 -0
  65. package/dist/types/auth.js.map +1 -0
  66. package/dist/types/block.d.ts +163 -0
  67. package/dist/types/block.d.ts.map +1 -0
  68. package/dist/types/block.js +77 -0
  69. package/dist/types/block.js.map +1 -0
  70. package/dist/types/bot.d.ts +42 -0
  71. package/dist/types/bot.d.ts.map +1 -0
  72. package/dist/types/bot.js +3 -0
  73. package/dist/types/bot.js.map +1 -0
  74. package/dist/types/chat-events.d.ts +191 -0
  75. package/dist/types/chat-events.d.ts.map +1 -0
  76. package/dist/types/chat-events.js +3 -0
  77. package/dist/types/chat-events.js.map +1 -0
  78. package/dist/types/common.d.ts +64 -0
  79. package/dist/types/common.d.ts.map +1 -0
  80. package/dist/types/common.js +3 -0
  81. package/dist/types/common.js.map +1 -0
  82. package/dist/types/conversation.d.ts +106 -0
  83. package/dist/types/conversation.d.ts.map +1 -0
  84. package/dist/types/conversation.js +3 -0
  85. package/dist/types/conversation.js.map +1 -0
  86. package/dist/types/file.d.ts +31 -0
  87. package/dist/types/file.d.ts.map +1 -0
  88. package/dist/types/file.js +3 -0
  89. package/dist/types/file.js.map +1 -0
  90. package/dist/types/message.d.ts +84 -0
  91. package/dist/types/message.d.ts.map +1 -0
  92. package/dist/types/message.js +3 -0
  93. package/dist/types/message.js.map +1 -0
  94. package/dist/types/notification-events.d.ts +89 -0
  95. package/dist/types/notification-events.d.ts.map +1 -0
  96. package/dist/types/notification-events.js +3 -0
  97. package/dist/types/notification-events.js.map +1 -0
  98. package/dist/types/participant.d.ts +22 -0
  99. package/dist/types/participant.d.ts.map +1 -0
  100. package/dist/types/participant.js +3 -0
  101. package/dist/types/participant.js.map +1 -0
  102. package/dist/types/signalr.d.ts +84 -0
  103. package/dist/types/signalr.d.ts.map +1 -0
  104. package/dist/types/signalr.js +3 -0
  105. package/dist/types/signalr.js.map +1 -0
  106. package/dist/utils/TypedEventEmitter.d.ts +32 -0
  107. package/dist/utils/TypedEventEmitter.d.ts.map +1 -0
  108. package/dist/utils/TypedEventEmitter.js +60 -0
  109. package/dist/utils/TypedEventEmitter.js.map +1 -0
  110. package/package.json +42 -0
@@ -0,0 +1,244 @@
1
+ // HttpClient.ts — Base HTTP client (fetch wrapper)
2
+ import { ChatApiError } from '../errors/ChatApiError.js';
3
+ /** Default per-request timeout (ms) when none is supplied. */
4
+ export const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
5
+ /**
6
+ * Base HTTP client wrapping the Fetch API.
7
+ *
8
+ * Features:
9
+ * - Automatic Authorization: Bearer token injection via tokenProvider
10
+ * - JSON request/response serialization
11
+ * - Throws ChatApiError on non-OK responses
12
+ * - Handles empty responses (204 No Content, 200 with no body) — the SDK
13
+ * convention is to type T as `null` or `void` for empty-body endpoints
14
+ * - Multipart file upload with optional XHR-based upload progress
15
+ * - Per-request timeout via AbortController (configurable, default 30s)
16
+ */
17
+ export class HttpClient {
18
+ constructor(options) {
19
+ // Strip trailing slash for consistent URL joining
20
+ this.baseUrl = options.baseUrl.replace(/\/$/, '');
21
+ this.tokenProvider = options.tokenProvider ?? (() => null);
22
+ this.requestTimeoutMs =
23
+ options.requestTimeoutMs === undefined ? DEFAULT_REQUEST_TIMEOUT_MS : options.requestTimeoutMs;
24
+ }
25
+ // ---------------------------------------------------------------------------
26
+ // Private helpers
27
+ // ---------------------------------------------------------------------------
28
+ buildUrl(path) {
29
+ // If path already looks absolute, use it directly
30
+ if (path.startsWith('http://') || path.startsWith('https://')) {
31
+ return path;
32
+ }
33
+ // Ensure exactly one slash between base and path
34
+ const separator = path.startsWith('/') ? '' : '/';
35
+ return `${this.baseUrl}${separator}${path}`;
36
+ }
37
+ buildHeaders(extra) {
38
+ const headers = {
39
+ 'Content-Type': 'application/json',
40
+ ...extra,
41
+ };
42
+ const token = this.tokenProvider();
43
+ if (token) {
44
+ headers['Authorization'] = `Bearer ${token}`;
45
+ }
46
+ return headers;
47
+ }
48
+ buildAuthHeader() {
49
+ const token = this.tokenProvider();
50
+ if (token) {
51
+ return { Authorization: `Bearer ${token}` };
52
+ }
53
+ return {};
54
+ }
55
+ /**
56
+ * Parse response body safely.
57
+ * Returns null for 204 No Content or empty bodies.
58
+ * Wraps JSON parse failures in ChatApiError for consistency with the XHR path.
59
+ */
60
+ async parseBody(response) {
61
+ if (response.status === 204)
62
+ return null;
63
+ const text = await response.text();
64
+ if (!text || text.trim() === '')
65
+ return null;
66
+ try {
67
+ return JSON.parse(text);
68
+ }
69
+ catch {
70
+ throw new ChatApiError(response.status, 'Parse Error', 'Failed to parse response JSON');
71
+ }
72
+ }
73
+ async handleResponse(response) {
74
+ if (!response.ok) {
75
+ throw await ChatApiError.fromResponse(response);
76
+ }
77
+ // Empty bodies (204 / empty 200) resolve as `null` cast to T. Public methods
78
+ // keep the `Promise<T>` signature; callers expecting an empty body should
79
+ // type T as `null` or `void` (see HttpClient.test.ts for the convention).
80
+ const result = await this.parseBody(response);
81
+ return result;
82
+ }
83
+ /**
84
+ * Run a fetch with an AbortController-based timeout.
85
+ * Throws ChatApiError(0, 'Timeout', ...) when the timeout fires before the
86
+ * response arrives. If `requestTimeoutMs` is null, fetch is used directly.
87
+ */
88
+ async fetchWithTimeout(input, init) {
89
+ const timeoutMs = this.requestTimeoutMs;
90
+ if (timeoutMs === null) {
91
+ return fetch(input, init);
92
+ }
93
+ const controller = new AbortController();
94
+ // Use an explicit flag instead of `controller.signal.aborted` so a network
95
+ // error that races with the timer firing is not misclassified as a timeout.
96
+ let timedOut = false;
97
+ const timer = setTimeout(() => {
98
+ timedOut = true;
99
+ controller.abort();
100
+ }, timeoutMs);
101
+ try {
102
+ return await fetch(input, { ...init, signal: controller.signal });
103
+ }
104
+ catch (err) {
105
+ if (timedOut) {
106
+ throw new ChatApiError(0, 'Timeout', `Request timed out after ${timeoutMs}ms`);
107
+ }
108
+ throw err;
109
+ }
110
+ finally {
111
+ clearTimeout(timer);
112
+ }
113
+ }
114
+ // ---------------------------------------------------------------------------
115
+ // Public methods
116
+ // ---------------------------------------------------------------------------
117
+ async get(path, headers) {
118
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
119
+ method: 'GET',
120
+ headers: { ...this.buildAuthHeader(), ...headers },
121
+ });
122
+ return this.handleResponse(response);
123
+ }
124
+ /**
125
+ * GET a plain-text response (e.g. /health/live which returns "Healthy").
126
+ * Unlike get<T>(), this does not attempt JSON parsing.
127
+ */
128
+ async getText(path) {
129
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
130
+ method: 'GET',
131
+ headers: { ...this.buildAuthHeader() },
132
+ });
133
+ if (!response.ok) {
134
+ throw await ChatApiError.fromResponse(response);
135
+ }
136
+ return response.text();
137
+ }
138
+ async post(path, body, headers) {
139
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
140
+ method: 'POST',
141
+ headers: { ...this.buildHeaders(headers) },
142
+ body: body !== undefined ? JSON.stringify(body) : undefined,
143
+ });
144
+ return this.handleResponse(response);
145
+ }
146
+ async patch(path, body, headers) {
147
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
148
+ method: 'PATCH',
149
+ headers: { ...this.buildHeaders(headers) },
150
+ body: body !== undefined ? JSON.stringify(body) : undefined,
151
+ });
152
+ return this.handleResponse(response);
153
+ }
154
+ async put(path, body, headers) {
155
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
156
+ method: 'PUT',
157
+ headers: { ...this.buildHeaders(headers) },
158
+ body: body !== undefined ? JSON.stringify(body) : undefined,
159
+ });
160
+ return this.handleResponse(response);
161
+ }
162
+ async delete(path, body, headers) {
163
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
164
+ method: 'DELETE',
165
+ headers: body !== undefined
166
+ ? { ...this.buildHeaders(headers) }
167
+ : { ...this.buildAuthHeader(), ...headers },
168
+ body: body !== undefined ? JSON.stringify(body) : undefined,
169
+ });
170
+ return this.handleResponse(response);
171
+ }
172
+ /**
173
+ * POST with multipart/form-data — no explicit Content-Type header
174
+ * (browser sets it with the boundary automatically).
175
+ */
176
+ async postFormData(path, formData) {
177
+ const response = await this.fetchWithTimeout(this.buildUrl(path), {
178
+ method: 'POST',
179
+ headers: { ...this.buildAuthHeader() },
180
+ body: formData,
181
+ });
182
+ return this.handleResponse(response);
183
+ }
184
+ /**
185
+ * POST with multipart/form-data and upload progress reporting.
186
+ * Uses XMLHttpRequest instead of fetch because fetch does not support
187
+ * upload progress events.
188
+ */
189
+ postFormDataWithProgress(path, formData, onProgress) {
190
+ return new Promise((resolve, reject) => {
191
+ const xhr = new XMLHttpRequest();
192
+ xhr.open('POST', this.buildUrl(path));
193
+ // Apply per-request timeout (null disables it)
194
+ if (this.requestTimeoutMs !== null) {
195
+ xhr.timeout = this.requestTimeoutMs;
196
+ }
197
+ const token = this.tokenProvider();
198
+ if (token) {
199
+ xhr.setRequestHeader('Authorization', `Bearer ${token}`);
200
+ }
201
+ if (onProgress) {
202
+ xhr.upload.onprogress = (event) => {
203
+ if (event.lengthComputable) {
204
+ onProgress(event.loaded, event.total);
205
+ }
206
+ };
207
+ }
208
+ xhr.onload = () => {
209
+ if (xhr.status >= 200 && xhr.status < 300) {
210
+ if (xhr.status === 204 || !xhr.responseText || xhr.responseText.trim() === '') {
211
+ // Empty body — same convention as fetch path: cast null to T.
212
+ resolve(null);
213
+ }
214
+ else {
215
+ try {
216
+ resolve(JSON.parse(xhr.responseText));
217
+ }
218
+ catch {
219
+ reject(new ChatApiError(xhr.status, 'Parse Error', 'Failed to parse response JSON'));
220
+ }
221
+ }
222
+ }
223
+ else {
224
+ // Build a minimal Response-like object to reuse ChatApiError.fromResponse.
225
+ // Use `.then(reject, reject)` so a thrown error from the parser is also surfaced.
226
+ const syntheticResponse = new Response(xhr.responseText, {
227
+ status: xhr.status,
228
+ statusText: xhr.statusText,
229
+ headers: { 'Content-Type': 'application/json' },
230
+ });
231
+ ChatApiError.fromResponse(syntheticResponse).then(reject, reject);
232
+ }
233
+ };
234
+ xhr.onerror = () => {
235
+ reject(new ChatApiError(0, 'Network Error', 'Request failed due to a network error'));
236
+ };
237
+ xhr.ontimeout = () => {
238
+ reject(new ChatApiError(0, 'Timeout', `Request timed out after ${xhr.timeout}ms`));
239
+ };
240
+ xhr.send(formData);
241
+ });
242
+ }
243
+ }
244
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/http/HttpClient.ts"],"names":[],"mappings":"AAAA,mDAAmD;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,8DAA8D;AAC9D,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAM,CAAC;AAajD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,UAAU;IAKrB,YAAY,OAA0B;QACpC,kDAAkD;QAClD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,CAAC,gBAAgB;YACnB,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;IACnG,CAAC;IAED,8EAA8E;IAC9E,kBAAkB;IAClB,8EAA8E;IAEtE,QAAQ,CAAC,IAAY;QAC3B,kDAAkD;QAClD,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,iDAAiD;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,OAAO,GAAG,IAAI,CAAC,OAAO,GAAG,SAAS,GAAG,IAAI,EAAE,CAAC;IAC9C,CAAC;IAEO,YAAY,CAAC,KAA8B;QACjD,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;YAClC,GAAG,KAAK;SACT,CAAC;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,eAAe;QACrB,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,SAAS,CAAI,QAAkB;QAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC;QAEzC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC;QAE7C,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,+BAA+B,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,cAAc,CAAI,QAAkB;QAChD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,MAAM,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;QACD,6EAA6E;QAC7E,0EAA0E;QAC1E,0EAA0E;QAC1E,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAI,QAAQ,CAAC,CAAC;QACjD,OAAO,MAAW,CAAC;IACrB,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,gBAAgB,CAAC,KAAa,EAAE,IAAiB;QAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACxC,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,QAAQ,GAAG,IAAI,CAAC;YAChB,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,2BAA2B,SAAS,IAAI,CAAC,CAAC;YACjF,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,iBAAiB;IACjB,8EAA8E;IAE9E,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,OAAgC;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,EAAE;SACnD,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,OAAO,CAAC,IAAY;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE;SACvC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,MAAM,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC;QAC1E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;YAC1C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,KAAK,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC;QAC3E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;YAC1C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC;QACzE,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;YAC1C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CAAI,IAAY,EAAE,IAAc,EAAE,OAAgC;QAC5E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE,IAAI,KAAK,SAAS;gBACzB,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;gBACnC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,OAAO,EAAE;YAC7C,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAI,IAAY,EAAE,QAAkB;QACpD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE;YACtC,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,CAAI,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACH,wBAAwB,CACtB,IAAY,EACZ,QAAkB,EAClB,UAAmC;QAEnC,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAEtC,+CAA+C;YAC/C,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;gBACnC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC;YACtC,CAAC;YAED,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,GAAG,CAAC,gBAAgB,CAAC,eAAe,EAAE,UAAU,KAAK,EAAE,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,UAAU,EAAE,CAAC;gBACf,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,CAAC,KAAK,EAAE,EAAE;oBAChC,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;wBAC3B,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;oBACxC,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC;YAED,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;gBAChB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;oBAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;wBAC9E,8DAA8D;wBAC9D,OAAO,CAAC,IAAoB,CAAC,CAAC;oBAChC,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC;4BACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAM,CAAC,CAAC;wBAC7C,CAAC;wBAAC,MAAM,CAAC;4BACP,MAAM,CAAC,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,+BAA+B,CAAC,CAAC,CAAC;wBACvF,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,2EAA2E;oBAC3E,kFAAkF;oBAClF,MAAM,iBAAiB,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,YAAY,EAAE;wBACvD,MAAM,EAAE,GAAG,CAAC,MAAM;wBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;wBAC1B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;qBAChD,CAAC,CAAC;oBACH,YAAY,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC,CAAC;YAEF,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;gBACjB,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,eAAe,EAAE,uCAAuC,CAAC,CAAC,CAAC;YACxF,CAAC,CAAC;YAEF,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE;gBACnB,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,2BAA2B,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC;YACrF,CAAC,CAAC;YAEF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;CAEF"}
@@ -0,0 +1,69 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { MessageDto, SendMessageRequest, EditMessageRequest } from '../types/message.js';
3
+ import type { CursorPaginatedResult } from '../types/common.js';
4
+ /**
5
+ * Message API client.
6
+ * All endpoints require JWT Bearer token.
7
+ */
8
+ export declare class MessageApi {
9
+ private readonly http;
10
+ constructor(http: HttpClient);
11
+ /**
12
+ * POST /api/conversations/{conversationId}/messages
13
+ * Send a new message. Returns 201 Created with the full MessageDto.
14
+ */
15
+ send(conversationId: string, request: SendMessageRequest): Promise<MessageDto>;
16
+ /**
17
+ * GET /api/conversations/{conversationId}/messages?limit={limit}&cursor={cursor}&direction={direction}
18
+ *
19
+ * Fetch message history with cursor-based pagination.
20
+ * direction: 'older' (default) loads messages older than cursor; 'newer' loads newer.
21
+ * NOTE: cursor is an opaque ULID message ID (e.g. "01JRZXYZ1234567890ABCDEF").
22
+ * Always treat as a string — NEVER cast to number.
23
+ */
24
+ getHistory(conversationId: string, params?: {
25
+ limit?: number;
26
+ cursor?: string;
27
+ direction?: 'older' | 'newer';
28
+ }): Promise<CursorPaginatedResult<MessageDto>>;
29
+ /**
30
+ * GET /api/conversations/{conversationId}/messages/search?q={query}&limit={limit}
31
+ * Full-text search within a conversation.
32
+ */
33
+ search(conversationId: string, query: string, limit?: number): Promise<MessageDto[]>;
34
+ /** GET /api/messages/{messageId} */
35
+ getById(messageId: string): Promise<MessageDto>;
36
+ /**
37
+ * PATCH /api/messages/{messageId}
38
+ * Edit message content. Only the original sender can edit.
39
+ * NOTE: REST uses { blocks, mentions } — different from SignalR ChatEditMessageRequest.
40
+ */
41
+ edit(messageId: string, request: EditMessageRequest): Promise<MessageDto>;
42
+ /**
43
+ * DELETE /api/messages/{messageId}
44
+ * Soft-delete a message. Returns { messageId, deletedAt } (not 204).
45
+ */
46
+ delete(messageId: string): Promise<{
47
+ messageId: string;
48
+ deletedAt: string;
49
+ }>;
50
+ /**
51
+ * POST /api/messages/{messageId}/recover
52
+ * Recover a soft-deleted message. Only available within 10 minutes of deletion.
53
+ * Returns 204 No Content. Call GET /api/messages/{messageId} afterwards if
54
+ * you need the recovered MessageDto.
55
+ */
56
+ recover(messageId: string): Promise<void>;
57
+ /**
58
+ * POST /api/messages/{messageId}/reactions
59
+ * Add an emoji reaction. Returns 409 Conflict if already reacted with the same emoji.
60
+ */
61
+ addReaction(messageId: string, emoji: string): Promise<void>;
62
+ /**
63
+ * DELETE /api/messages/{messageId}/reactions/{emoji}
64
+ * Remove an emoji reaction.
65
+ * emoji is automatically URL-encoded (required by the server).
66
+ */
67
+ removeReaction(messageId: string, emoji: string): Promise<void>;
68
+ }
69
+ //# sourceMappingURL=MessageApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageApi.d.ts","sourceRoot":"","sources":["../../src/http/MessageApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGhE;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;OAGG;IACH,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;IAa9E;;;;;;;OAOG;IACH,UAAU,CACR,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,GAC1E,OAAO,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAW7C;;;OAGG;IACH,MAAM,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAQpF,oCAAoC;IACpC,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI/C;;;;OAIG;IACH,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,UAAU,CAAC;IAWzE;;;OAGG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAM5E;;;;;OAKG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC;;;OAGG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D;;;;OAIG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKhE"}
@@ -0,0 +1,104 @@
1
+ // MessageApi.ts — Message operation endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ import { normalizeBlocksForSend } from '../types/block.js';
4
+ /**
5
+ * Message API client.
6
+ * All endpoints require JWT Bearer token.
7
+ */
8
+ export class MessageApi {
9
+ constructor(http) {
10
+ this.http = http;
11
+ }
12
+ /**
13
+ * POST /api/conversations/{conversationId}/messages
14
+ * Send a new message. Returns 201 Created with the full MessageDto.
15
+ */
16
+ send(conversationId, request) {
17
+ // Spec §6: `$type` must be the first property in each block when sent to
18
+ // the server, otherwise the polymorphic deserializer rejects the payload.
19
+ const normalized = {
20
+ ...request,
21
+ blocks: normalizeBlocksForSend(request.blocks),
22
+ };
23
+ return this.http.post(`/api/conversations/${encodeURIComponent(conversationId)}/messages`, normalized);
24
+ }
25
+ /**
26
+ * GET /api/conversations/{conversationId}/messages?limit={limit}&cursor={cursor}&direction={direction}
27
+ *
28
+ * Fetch message history with cursor-based pagination.
29
+ * direction: 'older' (default) loads messages older than cursor; 'newer' loads newer.
30
+ * NOTE: cursor is an opaque ULID message ID (e.g. "01JRZXYZ1234567890ABCDEF").
31
+ * Always treat as a string — NEVER cast to number.
32
+ */
33
+ getHistory(conversationId, params) {
34
+ const qs = new URLSearchParams();
35
+ if (params?.limit !== undefined)
36
+ qs.set('limit', String(params.limit));
37
+ if (params?.cursor !== undefined)
38
+ qs.set('cursor', params.cursor);
39
+ if (params?.direction !== undefined)
40
+ qs.set('direction', params.direction);
41
+ const q = qs.toString();
42
+ return this.http.get(`/api/conversations/${encodeURIComponent(conversationId)}/messages${q ? `?${q}` : ''}`);
43
+ }
44
+ /**
45
+ * GET /api/conversations/{conversationId}/messages/search?q={query}&limit={limit}
46
+ * Full-text search within a conversation.
47
+ */
48
+ search(conversationId, query, limit) {
49
+ const qs = new URLSearchParams({ q: query });
50
+ if (limit !== undefined)
51
+ qs.set('limit', String(limit));
52
+ return this.http.get(`/api/conversations/${encodeURIComponent(conversationId)}/messages/search?${qs.toString()}`);
53
+ }
54
+ /** GET /api/messages/{messageId} */
55
+ getById(messageId) {
56
+ return this.http.get(`/api/messages/${encodeURIComponent(messageId)}`);
57
+ }
58
+ /**
59
+ * PATCH /api/messages/{messageId}
60
+ * Edit message content. Only the original sender can edit.
61
+ * NOTE: REST uses { blocks, mentions } — different from SignalR ChatEditMessageRequest.
62
+ */
63
+ edit(messageId, request) {
64
+ const normalized = {
65
+ ...request,
66
+ blocks: normalizeBlocksForSend(request.blocks),
67
+ };
68
+ return this.http.patch(`/api/messages/${encodeURIComponent(messageId)}`, normalized);
69
+ }
70
+ /**
71
+ * DELETE /api/messages/{messageId}
72
+ * Soft-delete a message. Returns { messageId, deletedAt } (not 204).
73
+ */
74
+ delete(messageId) {
75
+ return this.http.delete(`/api/messages/${encodeURIComponent(messageId)}`);
76
+ }
77
+ /**
78
+ * POST /api/messages/{messageId}/recover
79
+ * Recover a soft-deleted message. Only available within 10 minutes of deletion.
80
+ * Returns 204 No Content. Call GET /api/messages/{messageId} afterwards if
81
+ * you need the recovered MessageDto.
82
+ */
83
+ recover(messageId) {
84
+ return this.http.post(`/api/messages/${encodeURIComponent(messageId)}/recover`);
85
+ }
86
+ /**
87
+ * POST /api/messages/{messageId}/reactions
88
+ * Add an emoji reaction. Returns 409 Conflict if already reacted with the same emoji.
89
+ */
90
+ addReaction(messageId, emoji) {
91
+ return this.http.post(`/api/messages/${encodeURIComponent(messageId)}/reactions`, {
92
+ emoji,
93
+ });
94
+ }
95
+ /**
96
+ * DELETE /api/messages/{messageId}/reactions/{emoji}
97
+ * Remove an emoji reaction.
98
+ * emoji is automatically URL-encoded (required by the server).
99
+ */
100
+ removeReaction(messageId, emoji) {
101
+ return this.http.delete(`/api/messages/${encodeURIComponent(messageId)}/reactions/${encodeURIComponent(emoji)}`);
102
+ }
103
+ }
104
+ //# sourceMappingURL=MessageApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageApi.js","sourceRoot":"","sources":["../../src/http/MessageApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { ParticipantDto, CreateOrUpdateParticipantRequest } from '../types/participant.js';
3
+ /**
4
+ * Participant API client.
5
+ * All endpoints require JWT Bearer token.
6
+ * GET endpoints are cached for 5 minutes on the server.
7
+ */
8
+ export declare class ParticipantApi {
9
+ private readonly http;
10
+ constructor(http: HttpClient);
11
+ /**
12
+ * POST /api/participants
13
+ * Create or update a participant (upsert by ID).
14
+ * Returns 201 Created for new participants, 200 OK for updates.
15
+ */
16
+ createOrUpdate(request: CreateOrUpdateParticipantRequest): Promise<ParticipantDto>;
17
+ /** GET /api/participants/{id} */
18
+ getById(id: string): Promise<ParticipantDto>;
19
+ /** GET /api/participants/by-uniquename/{uniqueName} */
20
+ getByUniqueName(uniqueName: string): Promise<ParticipantDto>;
21
+ /**
22
+ * POST /api/participants/batch
23
+ * Fetch multiple participants by an array of IDs in a single request.
24
+ * Returns only the participants that were found (missing IDs are silently skipped).
25
+ */
26
+ getBatch(ids: string[]): Promise<ParticipantDto[]>;
27
+ }
28
+ //# sourceMappingURL=ParticipantApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticipantApi.d.ts","sourceRoot":"","sources":["../../src/http/ParticipantApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,gCAAgC,EAAE,MAAM,yBAAyB,CAAC;AAEhG;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;OAIG;IACH,cAAc,CAAC,OAAO,EAAE,gCAAgC,GAAG,OAAO,CAAC,cAAc,CAAC;IAIlF,iCAAiC;IACjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAI5C,uDAAuD;IACvD,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAM5D;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;CAGnD"}
@@ -0,0 +1,37 @@
1
+ // ParticipantApi.ts — Participant management endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ /**
4
+ * Participant API client.
5
+ * All endpoints require JWT Bearer token.
6
+ * GET endpoints are cached for 5 minutes on the server.
7
+ */
8
+ export class ParticipantApi {
9
+ constructor(http) {
10
+ this.http = http;
11
+ }
12
+ /**
13
+ * POST /api/participants
14
+ * Create or update a participant (upsert by ID).
15
+ * Returns 201 Created for new participants, 200 OK for updates.
16
+ */
17
+ createOrUpdate(request) {
18
+ return this.http.post('/api/participants', request);
19
+ }
20
+ /** GET /api/participants/{id} */
21
+ getById(id) {
22
+ return this.http.get(`/api/participants/${encodeURIComponent(id)}`);
23
+ }
24
+ /** GET /api/participants/by-uniquename/{uniqueName} */
25
+ getByUniqueName(uniqueName) {
26
+ return this.http.get(`/api/participants/by-uniquename/${encodeURIComponent(uniqueName)}`);
27
+ }
28
+ /**
29
+ * POST /api/participants/batch
30
+ * Fetch multiple participants by an array of IDs in a single request.
31
+ * Returns only the participants that were found (missing IDs are silently skipped).
32
+ */
33
+ getBatch(ids) {
34
+ return this.http.post('/api/participants/batch', ids);
35
+ }
36
+ }
37
+ //# sourceMappingURL=ParticipantApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ParticipantApi.js","sourceRoot":"","sources":["../../src/http/ParticipantApi.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAGzB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,OAAyC;QACtD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAiB,mBAAmB,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,iCAAiC;IACjC,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAiB,qBAAqB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAED,uDAAuD;IACvD,eAAe,CAAC,UAAkB;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,mCAAmC,kBAAkB,CAAC,UAAU,CAAC,EAAE,CACpE,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,GAAa;QACpB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAmB,yBAAyB,EAAE,GAAG,CAAC,CAAC;IAC1E,CAAC;CACF"}
@@ -0,0 +1,59 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ /**
3
+ * Proxy API client.
4
+ * Forwards requests to registered backend services via the gateway.
5
+ *
6
+ * Example:
7
+ * proxy.get('trading', 'api/stocks/VN30')
8
+ * → GET /api/proxy/trading/api/stocks/VN30
9
+ *
10
+ * Auth: depends on the target service. Pass JWT when required.
11
+ * Error format: simple { "detail": "..." } — handled by ChatApiError.fromResponse().
12
+ */
13
+ export declare class ProxyApi {
14
+ private readonly http;
15
+ constructor(http: HttpClient);
16
+ /**
17
+ * Generic proxy request supporting any HTTP method.
18
+ *
19
+ * @param target - The registered backend target name (e.g. "trading")
20
+ * @param url - The URL path to forward, may include path and query string (e.g. "api/stocks/VN30?page=1")
21
+ * @param options.method - HTTP method (default: GET)
22
+ * @param options.body - Request body (for POST/PATCH)
23
+ * @param options.headers - Additional headers to forward
24
+ */
25
+ request<T>(target: string, url: string, options?: {
26
+ method?: string;
27
+ body?: unknown;
28
+ headers?: Record<string, string>;
29
+ }): Promise<T>;
30
+ /**
31
+ * GET /api/proxy/{target}/{url}
32
+ * Forward a GET request to the target service.
33
+ */
34
+ get<T>(target: string, url: string, headers?: Record<string, string>): Promise<T>;
35
+ /**
36
+ * POST /api/proxy/{target}/{url}
37
+ * Forward a POST request with an optional JSON body to the target service.
38
+ */
39
+ post<T>(target: string, url: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
40
+ /**
41
+ * PUT /api/proxy/{target}/{url}
42
+ * Forward a PUT request with an optional JSON body to the target service.
43
+ */
44
+ put<T>(target: string, url: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
45
+ /**
46
+ * PATCH /api/proxy/{target}/{url}
47
+ * Forward a PATCH request with an optional JSON body to the target service.
48
+ */
49
+ patch<T>(target: string, url: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
50
+ /**
51
+ * DELETE /api/proxy/{target}/{url}
52
+ * Forward a DELETE request to the target service. An optional JSON body is
53
+ * forwarded verbatim per spec §10.1 ("Forward HTTP method, query string,
54
+ * request body, và tất cả request headers").
55
+ */
56
+ delete<T>(target: string, url: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
57
+ private buildPath;
58
+ }
59
+ //# sourceMappingURL=ProxyApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProxyApi.d.ts","sourceRoot":"","sources":["../../src/http/ProxyApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;;;;;OAQG;IACH,OAAO,CAAC,CAAC,EACP,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAClC,GACA,OAAO,CAAC,CAAC,CAAC;IAkBb;;;OAGG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjF;;;OAGG;IACH,IAAI,CAAC,CAAC,EACJ,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAIb;;;OAGG;IACH,GAAG,CAAC,CAAC,EACH,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAIb;;;OAGG;IACH,KAAK,CAAC,CAAC,EACL,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAIb;;;;;OAKG;IACH,MAAM,CAAC,CAAC,EACN,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAIb,OAAO,CAAC,SAAS;CAIlB"}