@manonero/chat-client-sdk 1.0.0-beta.0

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 +2343 -0
  2. package/dist/ChatClient.d.ts +122 -0
  3. package/dist/ChatClient.d.ts.map +1 -0
  4. package/dist/ChatClient.js +173 -0
  5. package/dist/ChatClient.js.map +1 -0
  6. package/dist/errors/ChatApiError.d.ts +22 -0
  7. package/dist/errors/ChatApiError.d.ts.map +1 -0
  8. package/dist/errors/ChatApiError.js +50 -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 +50 -0
  15. package/dist/http/BotApi.d.ts.map +1 -0
  16. package/dist/http/BotApi.js +67 -0
  17. package/dist/http/BotApi.js.map +1 -0
  18. package/dist/http/ConversationApi.d.ts +81 -0
  19. package/dist/http/ConversationApi.d.ts.map +1 -0
  20. package/dist/http/ConversationApi.js +115 -0
  21. package/dist/http/ConversationApi.js.map +1 -0
  22. package/dist/http/FileApi.d.ts +48 -0
  23. package/dist/http/FileApi.d.ts.map +1 -0
  24. package/dist/http/FileApi.js +68 -0
  25. package/dist/http/FileApi.js.map +1 -0
  26. package/dist/http/HealthApi.d.ts +26 -0
  27. package/dist/http/HealthApi.d.ts.map +1 -0
  28. package/dist/http/HealthApi.js +31 -0
  29. package/dist/http/HealthApi.js.map +1 -0
  30. package/dist/http/HttpClient.d.ts +51 -0
  31. package/dist/http/HttpClient.d.ts.map +1 -0
  32. package/dist/http/HttpClient.js +182 -0
  33. package/dist/http/HttpClient.js.map +1 -0
  34. package/dist/http/MessageApi.d.ts +67 -0
  35. package/dist/http/MessageApi.d.ts.map +1 -0
  36. package/dist/http/MessageApi.js +91 -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 +41 -0
  43. package/dist/http/ProxyApi.d.ts.map +1 -0
  44. package/dist/http/ProxyApi.js +57 -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 +87 -0
  51. package/dist/realtime/ChatHubClient.d.ts.map +1 -0
  52. package/dist/realtime/ChatHubClient.js +182 -0
  53. package/dist/realtime/ChatHubClient.js.map +1 -0
  54. package/dist/realtime/NotificationHubClient.d.ts +73 -0
  55. package/dist/realtime/NotificationHubClient.d.ts.map +1 -0
  56. package/dist/realtime/NotificationHubClient.js +162 -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 +118 -0
  61. package/dist/realtime/ReconnectionManager.js.map +1 -0
  62. package/dist/types/auth.d.ts +28 -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 +148 -0
  67. package/dist/types/block.d.ts.map +1 -0
  68. package/dist/types/block.js +47 -0
  69. package/dist/types/block.js.map +1 -0
  70. package/dist/types/bot.d.ts +48 -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 +153 -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 +57 -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 +70 -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 +83 -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 +97 -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 +25 -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 +87 -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 +40 -0
@@ -0,0 +1,81 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { ConversationDto, ConversationListItemDto, ConversationParticipantDto, CreateConversationRequest, UpdateConversationRequest, AddParticipantRequest } from '../types/conversation.js';
3
+ import type { PaginatedResult } from '../types/common.js';
4
+ /**
5
+ * Conversation API client.
6
+ * All endpoints require JWT Bearer token.
7
+ */
8
+ export declare class ConversationApi {
9
+ private readonly http;
10
+ constructor(http: HttpClient);
11
+ /**
12
+ * GET /api/conversations?limit={limit}&cursor={cursor}
13
+ *
14
+ * Returns paginated conversations sorted by:
15
+ * 1. Pinned conversations first (by pinnedAt desc)
16
+ * 2. Then by lastMessageAt desc
17
+ *
18
+ * Each item includes the full lastMessage (MessageDto) for preview.
19
+ * NOTE: cursor is a string representing .NET DateTime ticks — do NOT cast to number.
20
+ */
21
+ list(params?: {
22
+ limit?: number;
23
+ cursor?: string;
24
+ }): Promise<PaginatedResult<ConversationListItemDto>>;
25
+ /** POST /api/conversations */
26
+ create(request: CreateConversationRequest): Promise<ConversationDto>;
27
+ /**
28
+ * GET /api/conversations/search?q={query}&limit={limit}
29
+ * Search conversations by name or participant name.
30
+ */
31
+ search(query: string, limit?: number): Promise<ConversationListItemDto[]>;
32
+ /** GET /api/conversations/{id} */
33
+ getById(id: string): Promise<ConversationDto>;
34
+ /**
35
+ * PATCH /api/conversations/{id}
36
+ * Only applicable for Group conversations.
37
+ */
38
+ update(id: string, request: UpdateConversationRequest): Promise<ConversationDto>;
39
+ /**
40
+ * DELETE /api/conversations/{id}
41
+ * Leave the conversation. Does NOT delete it — other participants remain.
42
+ */
43
+ leave(id: string): Promise<void>;
44
+ /**
45
+ * GET /api/conversations/one-to-one/{otherParticipantId}
46
+ * Find an existing OneToOne conversation with another participant.
47
+ * Returns null (204 No Content) when no such conversation exists yet.
48
+ */
49
+ findOneToOne(otherParticipantId: string): Promise<ConversationDto | null>;
50
+ /**
51
+ * POST /api/conversations/{id}/participants
52
+ * Add a participant to a Group conversation.
53
+ * canViewHistory defaults to true (can see messages before joining).
54
+ */
55
+ addParticipant(conversationId: string, request: AddParticipantRequest): Promise<void>;
56
+ /**
57
+ * DELETE /api/conversations/{id}/participants/{participantId}
58
+ * Remove a participant from a Group conversation.
59
+ */
60
+ removeParticipant(conversationId: string, participantId: string): Promise<void>;
61
+ /**
62
+ * GET /api/conversations/{id}/participants
63
+ * Returns all participants (including those who have left).
64
+ */
65
+ getParticipants(conversationId: string): Promise<ConversationParticipantDto[]>;
66
+ /** POST /api/conversations/{id}/pin */
67
+ pin(id: string): Promise<void>;
68
+ /** DELETE /api/conversations/{id}/pin */
69
+ unpin(id: string): Promise<void>;
70
+ /**
71
+ * POST /api/conversations/{id}/read
72
+ * Mark a conversation as read up to the given messageId.
73
+ */
74
+ markAsRead(id: string, messageId: string): Promise<void>;
75
+ /**
76
+ * DELETE /api/conversations/{id}/read
77
+ * Mark the conversation as unread (user-initiated).
78
+ */
79
+ markAsUnread(id: string): Promise<void>;
80
+ }
81
+ //# sourceMappingURL=ConversationApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationApi.d.ts","sourceRoot":"","sources":["../../src/http/ConversationApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EACV,eAAe,EACf,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE1D;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;;;;;;OASG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;IAUrD,8BAA8B;IAC9B,MAAM,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC;IAIpE;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAMzE,kCAAkC;IAClC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI7C;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC;IAIhF;;;OAGG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;OAIG;IACH,YAAY,CAAC,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAMzE;;;;OAIG;IACH,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrF;;;OAGG;IACH,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/E;;;OAGG;IACH,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,EAAE,CAAC;IAM9E,uCAAuC;IACvC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9B,yCAAyC;IACzC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC;;;OAGG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxD;;;OAGG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGxC"}
@@ -0,0 +1,115 @@
1
+ // ConversationApi.ts — Conversation management endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ /**
4
+ * Conversation API client.
5
+ * All endpoints require JWT Bearer token.
6
+ */
7
+ export class ConversationApi {
8
+ constructor(http) {
9
+ this.http = http;
10
+ }
11
+ /**
12
+ * GET /api/conversations?limit={limit}&cursor={cursor}
13
+ *
14
+ * Returns paginated conversations sorted by:
15
+ * 1. Pinned conversations first (by pinnedAt desc)
16
+ * 2. Then by lastMessageAt desc
17
+ *
18
+ * Each item includes the full lastMessage (MessageDto) for preview.
19
+ * NOTE: cursor is a string representing .NET DateTime ticks — do NOT cast to number.
20
+ */
21
+ list(params) {
22
+ const qs = new URLSearchParams();
23
+ if (params?.limit !== undefined)
24
+ qs.set('limit', String(params.limit));
25
+ if (params?.cursor !== undefined)
26
+ qs.set('cursor', params.cursor);
27
+ const q = qs.toString();
28
+ return this.http.get(`/api/conversations${q ? `?${q}` : ''}`);
29
+ }
30
+ /** POST /api/conversations */
31
+ create(request) {
32
+ return this.http.post('/api/conversations', request);
33
+ }
34
+ /**
35
+ * GET /api/conversations/search?q={query}&limit={limit}
36
+ * Search conversations by name or participant name.
37
+ */
38
+ search(query, limit) {
39
+ const qs = new URLSearchParams({ q: query });
40
+ if (limit !== undefined)
41
+ qs.set('limit', String(limit));
42
+ return this.http.get(`/api/conversations/search?${qs.toString()}`);
43
+ }
44
+ /** GET /api/conversations/{id} */
45
+ getById(id) {
46
+ return this.http.get(`/api/conversations/${encodeURIComponent(id)}`);
47
+ }
48
+ /**
49
+ * PATCH /api/conversations/{id}
50
+ * Only applicable for Group conversations.
51
+ */
52
+ update(id, request) {
53
+ return this.http.patch(`/api/conversations/${encodeURIComponent(id)}`, request);
54
+ }
55
+ /**
56
+ * DELETE /api/conversations/{id}
57
+ * Leave the conversation. Does NOT delete it — other participants remain.
58
+ */
59
+ leave(id) {
60
+ return this.http.delete(`/api/conversations/${encodeURIComponent(id)}`);
61
+ }
62
+ /**
63
+ * GET /api/conversations/one-to-one/{otherParticipantId}
64
+ * Find an existing OneToOne conversation with another participant.
65
+ * Returns null (204 No Content) when no such conversation exists yet.
66
+ */
67
+ findOneToOne(otherParticipantId) {
68
+ return this.http.get(`/api/conversations/one-to-one/${encodeURIComponent(otherParticipantId)}`);
69
+ }
70
+ /**
71
+ * POST /api/conversations/{id}/participants
72
+ * Add a participant to a Group conversation.
73
+ * canViewHistory defaults to true (can see messages before joining).
74
+ */
75
+ addParticipant(conversationId, request) {
76
+ return this.http.post(`/api/conversations/${encodeURIComponent(conversationId)}/participants`, request);
77
+ }
78
+ /**
79
+ * DELETE /api/conversations/{id}/participants/{participantId}
80
+ * Remove a participant from a Group conversation.
81
+ */
82
+ removeParticipant(conversationId, participantId) {
83
+ return this.http.delete(`/api/conversations/${encodeURIComponent(conversationId)}/participants/${encodeURIComponent(participantId)}`);
84
+ }
85
+ /**
86
+ * GET /api/conversations/{id}/participants
87
+ * Returns all participants (including those who have left).
88
+ */
89
+ getParticipants(conversationId) {
90
+ return this.http.get(`/api/conversations/${encodeURIComponent(conversationId)}/participants`);
91
+ }
92
+ /** POST /api/conversations/{id}/pin */
93
+ pin(id) {
94
+ return this.http.post(`/api/conversations/${encodeURIComponent(id)}/pin`);
95
+ }
96
+ /** DELETE /api/conversations/{id}/pin */
97
+ unpin(id) {
98
+ return this.http.delete(`/api/conversations/${encodeURIComponent(id)}/pin`);
99
+ }
100
+ /**
101
+ * POST /api/conversations/{id}/read
102
+ * Mark a conversation as read up to the given messageId.
103
+ */
104
+ markAsRead(id, messageId) {
105
+ return this.http.post(`/api/conversations/${encodeURIComponent(id)}/read`, { messageId });
106
+ }
107
+ /**
108
+ * DELETE /api/conversations/{id}/read
109
+ * Mark the conversation as unread (user-initiated).
110
+ */
111
+ markAsUnread(id) {
112
+ return this.http.delete(`/api/conversations/${encodeURIComponent(id)}/read`);
113
+ }
114
+ }
115
+ //# sourceMappingURL=ConversationApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConversationApi.js","sourceRoot":"","sources":["../../src/http/ConversationApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { CreateUploadUrlRequest, CreateUploadUrlResponse, UploadResponse } from '../types/file.js';
3
+ import type { UploadProgressCallback } from '../types/common.js';
4
+ /**
5
+ * File API client.
6
+ * Upload endpoints require JWT Bearer token.
7
+ * Download (GET /api/files/*) is public — no JWT required.
8
+ */
9
+ export declare class FileApi {
10
+ private readonly http;
11
+ constructor(http: HttpClient);
12
+ /**
13
+ * POST /api/files/upload-url
14
+ * Request a presigned upload URL. Returns a relative uploadUrl that must
15
+ * be combined with baseUrl before calling upload().
16
+ */
17
+ createUploadUrl(request: CreateUploadUrlRequest): Promise<CreateUploadUrlResponse>;
18
+ /**
19
+ * POST {uploadUrl} (relative URL from createUploadUrl response)
20
+ * Upload the file using multipart/form-data under the field name "file".
21
+ *
22
+ * When onProgress is provided, XHR is used (supports upload progress events).
23
+ * Otherwise fetch is used.
24
+ *
25
+ * NOTE: uploadUrl from the server is a relative path like "/api/files/upload?key=...&sig=...".
26
+ * HttpClient.buildUrl() automatically prepends baseUrl for relative paths.
27
+ */
28
+ upload(uploadUrl: string, file: File | Blob, onProgress?: UploadProgressCallback): Promise<UploadResponse>;
29
+ /**
30
+ * Returns the absolute download URL for a given storageKey.
31
+ * Download is public — no auth required.
32
+ * Example: storageKey "01HXABCDEF/photo.jpg" → "{baseUrl}/api/files/01HXABCDEF/photo.jpg"
33
+ */
34
+ getDownloadUrl(storageKey: string): string;
35
+ /**
36
+ * DELETE /api/files/{storageKey}
37
+ * Delete an uploaded file. Only the uploader can delete.
38
+ * storageKey may contain path separators (e.g. "01HXABCDEF/photo.jpg") — do NOT encode it.
39
+ */
40
+ delete(storageKey: string): Promise<void>;
41
+ /**
42
+ * Convenience method: create upload URL then immediately upload the file.
43
+ * Equivalent to calling createUploadUrl() + upload() in sequence.
44
+ * onProgress is forwarded to the upload step.
45
+ */
46
+ uploadFile(file: File, onProgress?: UploadProgressCallback): Promise<UploadResponse>;
47
+ }
48
+ //# sourceMappingURL=FileApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileApi.d.ts","sourceRoot":"","sources":["../../src/http/FileApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EACV,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE;;;;GAIG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAIlF;;;;;;;;;OASG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,IAAI,GAAG,IAAI,EACjB,UAAU,CAAC,EAAE,sBAAsB,GAClC,OAAO,CAAC,cAAc,CAAC;IAS1B;;;;OAIG;IACH,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAI1C;;;;OAIG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC;;;;OAIG;IACG,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,cAAc,CAAC;CAQ3F"}
@@ -0,0 +1,68 @@
1
+ // FileApi.ts — File upload/download endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ /**
4
+ * File API client.
5
+ * Upload endpoints require JWT Bearer token.
6
+ * Download (GET /api/files/*) is public — no JWT required.
7
+ */
8
+ export class FileApi {
9
+ constructor(http) {
10
+ this.http = http;
11
+ }
12
+ /**
13
+ * POST /api/files/upload-url
14
+ * Request a presigned upload URL. Returns a relative uploadUrl that must
15
+ * be combined with baseUrl before calling upload().
16
+ */
17
+ createUploadUrl(request) {
18
+ return this.http.post('/api/files/upload-url', request);
19
+ }
20
+ /**
21
+ * POST {uploadUrl} (relative URL from createUploadUrl response)
22
+ * Upload the file using multipart/form-data under the field name "file".
23
+ *
24
+ * When onProgress is provided, XHR is used (supports upload progress events).
25
+ * Otherwise fetch is used.
26
+ *
27
+ * NOTE: uploadUrl from the server is a relative path like "/api/files/upload?key=...&sig=...".
28
+ * HttpClient.buildUrl() automatically prepends baseUrl for relative paths.
29
+ */
30
+ upload(uploadUrl, file, onProgress) {
31
+ const formData = new FormData();
32
+ formData.append('file', file);
33
+ if (onProgress) {
34
+ return this.http.postFormDataWithProgress(uploadUrl, formData, onProgress);
35
+ }
36
+ return this.http.postFormData(uploadUrl, formData);
37
+ }
38
+ /**
39
+ * Returns the absolute download URL for a given storageKey.
40
+ * Download is public — no auth required.
41
+ * Example: storageKey "01HXABCDEF/photo.jpg" → "{baseUrl}/api/files/01HXABCDEF/photo.jpg"
42
+ */
43
+ getDownloadUrl(storageKey) {
44
+ return `${this.http.baseUrl}/api/files/${storageKey}`;
45
+ }
46
+ /**
47
+ * DELETE /api/files/{storageKey}
48
+ * Delete an uploaded file. Only the uploader can delete.
49
+ * storageKey may contain path separators (e.g. "01HXABCDEF/photo.jpg") — do NOT encode it.
50
+ */
51
+ delete(storageKey) {
52
+ return this.http.delete(`/api/files/${storageKey}`);
53
+ }
54
+ /**
55
+ * Convenience method: create upload URL then immediately upload the file.
56
+ * Equivalent to calling createUploadUrl() + upload() in sequence.
57
+ * onProgress is forwarded to the upload step.
58
+ */
59
+ async uploadFile(file, onProgress) {
60
+ const { uploadUrl } = await this.createUploadUrl({
61
+ fileName: file.name,
62
+ contentType: file.type,
63
+ fileSize: file.size,
64
+ });
65
+ return this.upload(uploadUrl, file, onProgress);
66
+ }
67
+ }
68
+ //# sourceMappingURL=FileApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileApi.js","sourceRoot":"","sources":["../../src/http/FileApi.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQ7C;;;;GAIG;AACH,MAAM,OAAO,OAAO;IAGlB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,eAAe,CAAC,OAA+B;QAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAA0B,uBAAuB,EAAE,OAAO,CAAC,CAAC;IACnF,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CACJ,SAAiB,EACjB,IAAiB,EACjB,UAAmC;QAEnC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;QAChC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9B,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAiB,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC7F,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAiB,SAAS,EAAE,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED;;;;OAIG;IACH,cAAc,CAAC,UAAkB;QAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,cAAc,UAAU,EAAE,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,UAAkB;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAO,cAAc,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,IAAU,EAAE,UAAmC;QAC9D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC;YAC/C,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,WAAW,EAAE,IAAI,CAAC,IAAI;YACtB,QAAQ,EAAE,IAAI,CAAC,IAAI;SACpB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAClD,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { HealthStatus } from '../types/common.js';
3
+ /**
4
+ * Health check API client.
5
+ * All endpoints are public — no JWT required.
6
+ */
7
+ export declare class HealthApi {
8
+ private readonly http;
9
+ constructor(http: HttpClient);
10
+ /**
11
+ * GET /health/live
12
+ * Liveness probe — returns the plain text string "Healthy" when the server is up.
13
+ * Use this to check if the process is running (not whether dependencies are healthy).
14
+ */
15
+ live(): Promise<string>;
16
+ /**
17
+ * GET /health/ready
18
+ * Readiness probe — returns detailed status for all dependencies
19
+ * (MongoDB, Redis, Kafka). Use this to check if the server can serve traffic.
20
+ *
21
+ * status values: "Healthy" | "Degraded" | "Unhealthy"
22
+ * durations are .NET TimeSpan strings (e.g. "00:00:00.1234567"), NOT numbers.
23
+ */
24
+ ready(): Promise<HealthStatus>;
25
+ }
26
+ //# sourceMappingURL=HealthApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthApi.d.ts","sourceRoot":"","sources":["../../src/http/HealthApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;GAGG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;OAIG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvB;;;;;;;OAOG;IACH,KAAK,IAAI,OAAO,CAAC,YAAY,CAAC;CAG/B"}
@@ -0,0 +1,31 @@
1
+ // HealthApi.ts — Health check endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ /**
4
+ * Health check API client.
5
+ * All endpoints are public — no JWT required.
6
+ */
7
+ export class HealthApi {
8
+ constructor(http) {
9
+ this.http = http;
10
+ }
11
+ /**
12
+ * GET /health/live
13
+ * Liveness probe — returns the plain text string "Healthy" when the server is up.
14
+ * Use this to check if the process is running (not whether dependencies are healthy).
15
+ */
16
+ live() {
17
+ return this.http.getText('/health/live');
18
+ }
19
+ /**
20
+ * GET /health/ready
21
+ * Readiness probe — returns detailed status for all dependencies
22
+ * (MongoDB, Redis, Kafka). Use this to check if the server can serve traffic.
23
+ *
24
+ * status values: "Healthy" | "Degraded" | "Unhealthy"
25
+ * durations are .NET TimeSpan strings (e.g. "00:00:00.1234567"), NOT numbers.
26
+ */
27
+ ready() {
28
+ return this.http.get('/health/ready');
29
+ }
30
+ }
31
+ //# sourceMappingURL=HealthApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HealthApi.js","sourceRoot":"","sources":["../../src/http/HealthApi.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C;;;GAGG;AACH,MAAM,OAAO,SAAS;IAGpB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK;QACH,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAe,eAAe,CAAC,CAAC;IACtD,CAAC;CACF"}
@@ -0,0 +1,51 @@
1
+ import type { UploadProgressCallback } from '../types/common.js';
2
+ export interface HttpClientOptions {
3
+ baseUrl: string;
4
+ /** Returns the current JWT token, or null if not authenticated */
5
+ tokenProvider?: () => string | null;
6
+ }
7
+ /**
8
+ * Base HTTP client wrapping the Fetch API.
9
+ *
10
+ * Features:
11
+ * - Automatic Authorization: Bearer token injection via tokenProvider
12
+ * - JSON request/response serialization
13
+ * - Throws ChatApiError on non-OK responses
14
+ * - Handles empty responses (204 No Content, 200 with no body)
15
+ * - Multipart file upload with optional XHR-based upload progress
16
+ */
17
+ export declare class HttpClient {
18
+ readonly baseUrl: string;
19
+ private readonly tokenProvider;
20
+ constructor(options: HttpClientOptions);
21
+ private buildUrl;
22
+ private buildHeaders;
23
+ private buildAuthHeader;
24
+ /**
25
+ * Parse response body safely.
26
+ * Returns null for 204 No Content or empty bodies.
27
+ */
28
+ private parseBody;
29
+ private handleResponse;
30
+ get<T>(path: string, headers?: Record<string, string>): Promise<T>;
31
+ /**
32
+ * GET a plain-text response (e.g. /health/live which returns "Healthy").
33
+ * Unlike get<T>(), this does not attempt JSON parsing.
34
+ */
35
+ getText(path: string): Promise<string>;
36
+ post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
37
+ patch<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
38
+ delete<T>(path: string, headers?: Record<string, string>): Promise<T>;
39
+ /**
40
+ * POST with multipart/form-data — no explicit Content-Type header
41
+ * (browser sets it with the boundary automatically).
42
+ */
43
+ postFormData<T>(path: string, formData: FormData): Promise<T>;
44
+ /**
45
+ * POST with multipart/form-data and upload progress reporting.
46
+ * Uses XMLHttpRequest instead of fetch because fetch does not support
47
+ * upload progress events.
48
+ */
49
+ postFormDataWithProgress<T>(path: string, formData: FormData, onProgress?: UploadProgressCallback): Promise<T>;
50
+ }
51
+ //# sourceMappingURL=HttpClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.d.ts","sourceRoot":"","sources":["../../src/http/HttpClient.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;;;;;;GASG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;gBAExC,OAAO,EAAE,iBAAiB;IAUtC,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,eAAe;IAQvB;;;OAGG;YACW,SAAS;YAST,cAAc;IAatB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAQxE;;;OAGG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWtC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASnF,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IASpF,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAQ3E;;;OAGG;IACG,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IASnE;;;;OAIG;IACH,wBAAwB,CAAC,CAAC,EACxB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,UAAU,CAAC,EAAE,sBAAsB,GAClC,OAAO,CAAC,CAAC,CAAC;CAoDd"}
@@ -0,0 +1,182 @@
1
+ // HttpClient.ts — Base HTTP client (fetch wrapper)
2
+ import { ChatApiError } from '../errors/ChatApiError.js';
3
+ /**
4
+ * Base HTTP client wrapping the Fetch API.
5
+ *
6
+ * Features:
7
+ * - Automatic Authorization: Bearer token injection via tokenProvider
8
+ * - JSON request/response serialization
9
+ * - Throws ChatApiError on non-OK responses
10
+ * - Handles empty responses (204 No Content, 200 with no body)
11
+ * - Multipart file upload with optional XHR-based upload progress
12
+ */
13
+ export class HttpClient {
14
+ constructor(options) {
15
+ // Strip trailing slash for consistent URL joining
16
+ this.baseUrl = options.baseUrl.replace(/\/$/, '');
17
+ this.tokenProvider = options.tokenProvider ?? (() => null);
18
+ }
19
+ // ---------------------------------------------------------------------------
20
+ // Private helpers
21
+ // ---------------------------------------------------------------------------
22
+ buildUrl(path) {
23
+ // If path already looks absolute, use it directly
24
+ if (path.startsWith('http://') || path.startsWith('https://')) {
25
+ return path;
26
+ }
27
+ // Ensure exactly one slash between base and path
28
+ const separator = path.startsWith('/') ? '' : '/';
29
+ return `${this.baseUrl}${separator}${path}`;
30
+ }
31
+ buildHeaders(extra) {
32
+ const headers = {
33
+ 'Content-Type': 'application/json',
34
+ ...extra,
35
+ };
36
+ const token = this.tokenProvider();
37
+ if (token) {
38
+ headers['Authorization'] = `Bearer ${token}`;
39
+ }
40
+ return headers;
41
+ }
42
+ buildAuthHeader() {
43
+ const token = this.tokenProvider();
44
+ if (token) {
45
+ return { Authorization: `Bearer ${token}` };
46
+ }
47
+ return {};
48
+ }
49
+ /**
50
+ * Parse response body safely.
51
+ * Returns null for 204 No Content or empty bodies.
52
+ */
53
+ async parseBody(response) {
54
+ if (response.status === 204)
55
+ return null;
56
+ const text = await response.text();
57
+ if (!text || text.trim() === '')
58
+ return null;
59
+ return JSON.parse(text);
60
+ }
61
+ async handleResponse(response) {
62
+ if (!response.ok) {
63
+ throw await ChatApiError.fromResponse(response);
64
+ }
65
+ // Reuse the body text that was already consumed — clone before parseBody
66
+ const result = await this.parseBody(response);
67
+ return result;
68
+ }
69
+ // ---------------------------------------------------------------------------
70
+ // Public methods
71
+ // ---------------------------------------------------------------------------
72
+ async get(path, headers) {
73
+ const response = await fetch(this.buildUrl(path), {
74
+ method: 'GET',
75
+ headers: { ...this.buildAuthHeader(), ...headers },
76
+ });
77
+ return this.handleResponse(response);
78
+ }
79
+ /**
80
+ * GET a plain-text response (e.g. /health/live which returns "Healthy").
81
+ * Unlike get<T>(), this does not attempt JSON parsing.
82
+ */
83
+ async getText(path) {
84
+ const response = await fetch(this.buildUrl(path), {
85
+ method: 'GET',
86
+ headers: { ...this.buildAuthHeader() },
87
+ });
88
+ if (!response.ok) {
89
+ throw await ChatApiError.fromResponse(response);
90
+ }
91
+ return response.text();
92
+ }
93
+ async post(path, body, headers) {
94
+ const response = await fetch(this.buildUrl(path), {
95
+ method: 'POST',
96
+ headers: { ...this.buildHeaders(headers) },
97
+ body: body !== undefined ? JSON.stringify(body) : undefined,
98
+ });
99
+ return this.handleResponse(response);
100
+ }
101
+ async patch(path, body, headers) {
102
+ const response = await fetch(this.buildUrl(path), {
103
+ method: 'PATCH',
104
+ headers: { ...this.buildHeaders(headers) },
105
+ body: body !== undefined ? JSON.stringify(body) : undefined,
106
+ });
107
+ return this.handleResponse(response);
108
+ }
109
+ async delete(path, headers) {
110
+ const response = await fetch(this.buildUrl(path), {
111
+ method: 'DELETE',
112
+ headers: { ...this.buildAuthHeader(), ...headers },
113
+ });
114
+ return this.handleResponse(response);
115
+ }
116
+ /**
117
+ * POST with multipart/form-data — no explicit Content-Type header
118
+ * (browser sets it with the boundary automatically).
119
+ */
120
+ async postFormData(path, formData) {
121
+ const response = await fetch(this.buildUrl(path), {
122
+ method: 'POST',
123
+ headers: { ...this.buildAuthHeader() },
124
+ body: formData,
125
+ });
126
+ return this.handleResponse(response);
127
+ }
128
+ /**
129
+ * POST with multipart/form-data and upload progress reporting.
130
+ * Uses XMLHttpRequest instead of fetch because fetch does not support
131
+ * upload progress events.
132
+ */
133
+ postFormDataWithProgress(path, formData, onProgress) {
134
+ return new Promise((resolve, reject) => {
135
+ const xhr = new XMLHttpRequest();
136
+ xhr.open('POST', this.buildUrl(path));
137
+ const token = this.tokenProvider();
138
+ if (token) {
139
+ xhr.setRequestHeader('Authorization', `Bearer ${token}`);
140
+ }
141
+ if (onProgress) {
142
+ xhr.upload.onprogress = (event) => {
143
+ if (event.lengthComputable) {
144
+ onProgress(event.loaded, event.total);
145
+ }
146
+ };
147
+ }
148
+ xhr.onload = () => {
149
+ if (xhr.status >= 200 && xhr.status < 300) {
150
+ if (xhr.status === 204 || !xhr.responseText || xhr.responseText.trim() === '') {
151
+ resolve(null);
152
+ }
153
+ else {
154
+ try {
155
+ resolve(JSON.parse(xhr.responseText));
156
+ }
157
+ catch {
158
+ reject(new ChatApiError(xhr.status, 'Parse Error', 'Failed to parse response JSON'));
159
+ }
160
+ }
161
+ }
162
+ else {
163
+ // Build a minimal Response-like object to reuse ChatApiError.fromResponse
164
+ const syntheticResponse = new Response(xhr.responseText, {
165
+ status: xhr.status,
166
+ statusText: xhr.statusText,
167
+ headers: { 'Content-Type': 'application/json' },
168
+ });
169
+ ChatApiError.fromResponse(syntheticResponse).then(reject).catch(reject);
170
+ }
171
+ };
172
+ xhr.onerror = () => {
173
+ reject(new ChatApiError(0, 'Network Error', 'Request failed due to a network error'));
174
+ };
175
+ xhr.ontimeout = () => {
176
+ reject(new ChatApiError(0, 'Timeout', 'Request timed out'));
177
+ };
178
+ xhr.send(formData);
179
+ });
180
+ }
181
+ }
182
+ //# sourceMappingURL=HttpClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpClient.js","sourceRoot":"","sources":["../../src/http/HttpClient.ts"],"names":[],"mappings":"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"}