@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,43 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { BotDto, CreateBotRequest, UpdateBotRequest } from '../types/bot.js';
3
+ import type { PagedResult } from '../types/common.js';
4
+ /**
5
+ * Bot API client.
6
+ *
7
+ * GET endpoints (list, getById) are public — no JWT required.
8
+ * Management endpoints (create, update, activate, deactivate, delete)
9
+ * require JWT with claim role=dev (obtained via loginWithDev).
10
+ * Non-dev users receive 404 Not Found on management endpoints.
11
+ */
12
+ export declare class BotApi {
13
+ private readonly http;
14
+ constructor(http: HttpClient);
15
+ /**
16
+ * GET /api/bots?page={page}&pageSize={pageSize}
17
+ * List all bots (public).
18
+ * page is 1-based.
19
+ */
20
+ list(params?: {
21
+ page?: number;
22
+ pageSize?: number;
23
+ }): Promise<PagedResult<BotDto>>;
24
+ /** GET /api/bots/{id} (public) */
25
+ getById(id: string): Promise<BotDto>;
26
+ /**
27
+ * POST /api/bots (dev-only)
28
+ * Register a new bot.
29
+ */
30
+ create(request: CreateBotRequest): Promise<BotDto>;
31
+ /**
32
+ * PATCH /api/bots/{id} (dev-only)
33
+ * Update bot metadata. kafkaTopic cannot be changed after creation.
34
+ */
35
+ update(id: string, request: UpdateBotRequest): Promise<BotDto>;
36
+ /** POST /api/bots/{id}/activate (dev-only) */
37
+ activate(id: string): Promise<void>;
38
+ /** POST /api/bots/{id}/deactivate (dev-only) */
39
+ deactivate(id: string): Promise<void>;
40
+ /** DELETE /api/bots/{id} (dev-only) — soft delete */
41
+ delete(id: string): Promise<void>;
42
+ }
43
+ //# sourceMappingURL=BotApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BotApi.d.ts","sourceRoot":"","sources":["../../src/http/BotApi.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;;;;;;GAOG;AACH,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;OAIG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAQjF,kCAAkC;IAClC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIpC;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlD;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9D,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInC,gDAAgD;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,qDAAqD;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlC"}
@@ -0,0 +1,60 @@
1
+ // BotApi.ts — Bot management endpoints
2
+ import { HttpClient } from './HttpClient.js';
3
+ /**
4
+ * Bot API client.
5
+ *
6
+ * GET endpoints (list, getById) are public — no JWT required.
7
+ * Management endpoints (create, update, activate, deactivate, delete)
8
+ * require JWT with claim role=dev (obtained via loginWithDev).
9
+ * Non-dev users receive 404 Not Found on management endpoints.
10
+ */
11
+ export class BotApi {
12
+ constructor(http) {
13
+ this.http = http;
14
+ }
15
+ /**
16
+ * GET /api/bots?page={page}&pageSize={pageSize}
17
+ * List all bots (public).
18
+ * page is 1-based.
19
+ */
20
+ list(params) {
21
+ const qs = new URLSearchParams();
22
+ if (params?.page !== undefined)
23
+ qs.set('page', String(params.page));
24
+ if (params?.pageSize !== undefined)
25
+ qs.set('pageSize', String(params.pageSize));
26
+ const q = qs.toString();
27
+ return this.http.get(`/api/bots${q ? `?${q}` : ''}`);
28
+ }
29
+ /** GET /api/bots/{id} (public) */
30
+ getById(id) {
31
+ return this.http.get(`/api/bots/${encodeURIComponent(id)}`);
32
+ }
33
+ /**
34
+ * POST /api/bots (dev-only)
35
+ * Register a new bot.
36
+ */
37
+ create(request) {
38
+ return this.http.post('/api/bots', request);
39
+ }
40
+ /**
41
+ * PATCH /api/bots/{id} (dev-only)
42
+ * Update bot metadata. kafkaTopic cannot be changed after creation.
43
+ */
44
+ update(id, request) {
45
+ return this.http.patch(`/api/bots/${encodeURIComponent(id)}`, request);
46
+ }
47
+ /** POST /api/bots/{id}/activate (dev-only) */
48
+ activate(id) {
49
+ return this.http.post(`/api/bots/${encodeURIComponent(id)}/activate`);
50
+ }
51
+ /** POST /api/bots/{id}/deactivate (dev-only) */
52
+ deactivate(id) {
53
+ return this.http.post(`/api/bots/${encodeURIComponent(id)}/deactivate`);
54
+ }
55
+ /** DELETE /api/bots/{id} (dev-only) — soft delete */
56
+ delete(id) {
57
+ return this.http.delete(`/api/bots/${encodeURIComponent(id)}`);
58
+ }
59
+ }
60
+ //# sourceMappingURL=BotApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BotApi.js","sourceRoot":"","sources":["../../src/http/BotApi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AAEvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7C;;;;;;;GAOG;AACH,MAAM,OAAO,MAAM;IAGjB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,MAA6C;QAChD,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS;YAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACpE,IAAI,MAAM,EAAE,QAAQ,KAAK,SAAS;YAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChF,MAAM,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAsB,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,kCAAkC;IAClC,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAS,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtE,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,OAAyB;QAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAS,WAAW,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,EAAU,EAAE,OAAyB;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAS,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACjF,CAAC;IAED,8CAA8C;IAC9C,QAAQ,CAAC,EAAU;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAO,aAAa,kBAAkB,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;IAC9E,CAAC;IAED,gDAAgD;IAChD,UAAU,CAAC,EAAU;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAO,aAAa,kBAAkB,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;IAChF,CAAC;IAED,qDAAqD;IACrD,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAO,aAAa,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;CACF"}
@@ -0,0 +1,92 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ import type { ConversationDto, ConversationListItemDto, ConversationMediaItemDto, ConversationMediaKindFilter, ConversationParticipantDto, CreateConversationRequest, UpdateConversationRequest, AddParticipantRequest } from '../types/conversation.js';
3
+ import type { CursorPaginatedResult } from '../types/common.js';
4
+ /**
5
+ * Conversation API client.
6
+ * All endpoints require JWT Bearer token.
7
+ *
8
+ * The system only supports Group conversations (spec §6.2); there is no
9
+ * direct 1-1 or self chat — a conversation with one user and one bot is
10
+ * still modelled as a 2-member Group.
11
+ */
12
+ export declare class ConversationApi {
13
+ private readonly http;
14
+ constructor(http: HttpClient);
15
+ /**
16
+ * GET /api/conversations?limit={limit}&cursor={cursor}
17
+ *
18
+ * Returns paginated conversations sorted by pinned first (by pinnedAt desc),
19
+ * then by lastMessageAt desc.
20
+ *
21
+ * Each item includes the full lastMessage (MessageDto) for preview. Clients
22
+ * MUST check `lastMessage.isDeleted` before displaying — the aggregator
23
+ * bypasses the deleted-filter (spec §6.1).
24
+ *
25
+ * NOTE: cursor is an opaque composite string "<UnixMs>_<ULID>". Always treat
26
+ * as a string — NEVER cast to number.
27
+ */
28
+ list(params?: {
29
+ limit?: number;
30
+ cursor?: string;
31
+ }): Promise<CursorPaginatedResult<ConversationListItemDto>>;
32
+ /** POST /api/conversations */
33
+ create(request: CreateConversationRequest): Promise<ConversationDto>;
34
+ /**
35
+ * GET /api/conversations/search?q={query}&limit={limit}
36
+ * Search conversations by name or participant name.
37
+ */
38
+ search(query: string, limit?: number): Promise<ConversationListItemDto[]>;
39
+ /** GET /api/conversations/{id} */
40
+ getById(id: string): Promise<ConversationDto>;
41
+ /** PATCH /api/conversations/{id} */
42
+ update(id: string, request: UpdateConversationRequest): Promise<ConversationDto>;
43
+ /**
44
+ * DELETE /api/conversations/{id}
45
+ * Alias for {@link leave}: the caller leaves the conversation; other
46
+ * participants keep it (spec §6.7).
47
+ */
48
+ delete(id: string): Promise<void>;
49
+ /**
50
+ * POST /api/conversations/{id}/leave
51
+ * Leave the conversation. Identical to {@link delete}; kept as a separate
52
+ * method because the spec exposes both URLs (spec §6.6).
53
+ */
54
+ leave(id: string): Promise<void>;
55
+ /**
56
+ * POST /api/conversations/{id}/participants
57
+ * Add a participant to the conversation.
58
+ */
59
+ addParticipant(conversationId: string, request: AddParticipantRequest): Promise<void>;
60
+ /**
61
+ * DELETE /api/conversations/{id}/participants/{participantId}
62
+ * Remove a participant from the conversation.
63
+ */
64
+ removeParticipant(conversationId: string, participantId: string): Promise<void>;
65
+ /**
66
+ * GET /api/conversations/{id}/participants
67
+ * Returns all participants (including those who have left).
68
+ */
69
+ getParticipants(conversationId: string): Promise<ConversationParticipantDto[]>;
70
+ /** POST /api/conversations/{id}/pin */
71
+ pin(id: string): Promise<void>;
72
+ /** DELETE /api/conversations/{id}/pin */
73
+ unpin(id: string): Promise<void>;
74
+ /**
75
+ * GET /api/conversations/{id}/media?kind={kind}&limit={limit}&cursor={cursor}
76
+ *
77
+ * List every media/link item that has appeared in the conversation, newest first.
78
+ *
79
+ * - `kind` — `all` (default), `attachment`, or `link` (case-insensitive on the wire).
80
+ * - `limit` — 1..100, default 50.
81
+ * - `cursor` — opaque `nextCursor` from a prior page.
82
+ *
83
+ * Participants only see items from messages created after they joined the
84
+ * conversation. Returns 403 if the caller is not a participant.
85
+ */
86
+ getMedia(conversationId: string, params?: {
87
+ kind?: ConversationMediaKindFilter;
88
+ limit?: number;
89
+ cursor?: string;
90
+ }): Promise<CursorPaginatedResult<ConversationMediaItemDto>>;
91
+ }
92
+ //# 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,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE;;;;;;;GAOG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,qBAAqB,CAAC,uBAAuB,CAAC,CAAC;IAU3D,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,oCAAoC;IACpC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,eAAe,CAAC;IAIhF;;;;OAIG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhC;;;OAGG;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;;;;;;;;;;;OAWG;IACH,QAAQ,CACN,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,2BAA2B,CAAC;QACnC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GACA,OAAO,CAAC,qBAAqB,CAAC,wBAAwB,CAAC,CAAC;CAU5D"}
@@ -0,0 +1,128 @@
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
+ * The system only supports Group conversations (spec §6.2); there is no
8
+ * direct 1-1 or self chat — a conversation with one user and one bot is
9
+ * still modelled as a 2-member Group.
10
+ */
11
+ export class ConversationApi {
12
+ constructor(http) {
13
+ this.http = http;
14
+ }
15
+ /**
16
+ * GET /api/conversations?limit={limit}&cursor={cursor}
17
+ *
18
+ * Returns paginated conversations sorted by pinned first (by pinnedAt desc),
19
+ * then by lastMessageAt desc.
20
+ *
21
+ * Each item includes the full lastMessage (MessageDto) for preview. Clients
22
+ * MUST check `lastMessage.isDeleted` before displaying — the aggregator
23
+ * bypasses the deleted-filter (spec §6.1).
24
+ *
25
+ * NOTE: cursor is an opaque composite string "<UnixMs>_<ULID>". Always treat
26
+ * as a string — NEVER cast to number.
27
+ */
28
+ list(params) {
29
+ const qs = new URLSearchParams();
30
+ if (params?.limit !== undefined)
31
+ qs.set('limit', String(params.limit));
32
+ if (params?.cursor !== undefined)
33
+ qs.set('cursor', params.cursor);
34
+ const q = qs.toString();
35
+ return this.http.get(`/api/conversations${q ? `?${q}` : ''}`);
36
+ }
37
+ /** POST /api/conversations */
38
+ create(request) {
39
+ return this.http.post('/api/conversations', request);
40
+ }
41
+ /**
42
+ * GET /api/conversations/search?q={query}&limit={limit}
43
+ * Search conversations by name or participant name.
44
+ */
45
+ search(query, limit) {
46
+ const qs = new URLSearchParams({ q: query });
47
+ if (limit !== undefined)
48
+ qs.set('limit', String(limit));
49
+ return this.http.get(`/api/conversations/search?${qs.toString()}`);
50
+ }
51
+ /** GET /api/conversations/{id} */
52
+ getById(id) {
53
+ return this.http.get(`/api/conversations/${encodeURIComponent(id)}`);
54
+ }
55
+ /** PATCH /api/conversations/{id} */
56
+ update(id, request) {
57
+ return this.http.patch(`/api/conversations/${encodeURIComponent(id)}`, request);
58
+ }
59
+ /**
60
+ * DELETE /api/conversations/{id}
61
+ * Alias for {@link leave}: the caller leaves the conversation; other
62
+ * participants keep it (spec §6.7).
63
+ */
64
+ delete(id) {
65
+ return this.http.delete(`/api/conversations/${encodeURIComponent(id)}`);
66
+ }
67
+ /**
68
+ * POST /api/conversations/{id}/leave
69
+ * Leave the conversation. Identical to {@link delete}; kept as a separate
70
+ * method because the spec exposes both URLs (spec §6.6).
71
+ */
72
+ leave(id) {
73
+ return this.http.post(`/api/conversations/${encodeURIComponent(id)}/leave`);
74
+ }
75
+ /**
76
+ * POST /api/conversations/{id}/participants
77
+ * Add a participant to the conversation.
78
+ */
79
+ addParticipant(conversationId, request) {
80
+ return this.http.post(`/api/conversations/${encodeURIComponent(conversationId)}/participants`, request);
81
+ }
82
+ /**
83
+ * DELETE /api/conversations/{id}/participants/{participantId}
84
+ * Remove a participant from the conversation.
85
+ */
86
+ removeParticipant(conversationId, participantId) {
87
+ return this.http.delete(`/api/conversations/${encodeURIComponent(conversationId)}/participants/${encodeURIComponent(participantId)}`);
88
+ }
89
+ /**
90
+ * GET /api/conversations/{id}/participants
91
+ * Returns all participants (including those who have left).
92
+ */
93
+ getParticipants(conversationId) {
94
+ return this.http.get(`/api/conversations/${encodeURIComponent(conversationId)}/participants`);
95
+ }
96
+ /** POST /api/conversations/{id}/pin */
97
+ pin(id) {
98
+ return this.http.post(`/api/conversations/${encodeURIComponent(id)}/pin`);
99
+ }
100
+ /** DELETE /api/conversations/{id}/pin */
101
+ unpin(id) {
102
+ return this.http.delete(`/api/conversations/${encodeURIComponent(id)}/pin`);
103
+ }
104
+ /**
105
+ * GET /api/conversations/{id}/media?kind={kind}&limit={limit}&cursor={cursor}
106
+ *
107
+ * List every media/link item that has appeared in the conversation, newest first.
108
+ *
109
+ * - `kind` — `all` (default), `attachment`, or `link` (case-insensitive on the wire).
110
+ * - `limit` — 1..100, default 50.
111
+ * - `cursor` — opaque `nextCursor` from a prior page.
112
+ *
113
+ * Participants only see items from messages created after they joined the
114
+ * conversation. Returns 403 if the caller is not a participant.
115
+ */
116
+ getMedia(conversationId, params) {
117
+ const qs = new URLSearchParams();
118
+ if (params?.kind !== undefined)
119
+ qs.set('kind', params.kind);
120
+ if (params?.limit !== undefined)
121
+ qs.set('limit', String(params.limit));
122
+ if (params?.cursor !== undefined)
123
+ qs.set('cursor', params.cursor);
124
+ const q = qs.toString();
125
+ return this.http.get(`/api/conversations/${encodeURIComponent(conversationId)}/media${q ? `?${q}` : ''}`);
126
+ }
127
+ }
128
+ //# 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,60 @@
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
+ *
32
+ * Default download is public — no auth required:
33
+ * getDownloadUrl("01HXABCDEF/photo.jpg")
34
+ * → "{baseUrl}/api/files/01HXABCDEF/photo.jpg"
35
+ *
36
+ * Pass `signed` to build a signed URL (spec §8.3) when the server enforces
37
+ * controlled access. Both `expires` and `sig` must be supplied — typically
38
+ * forwarded from the upload-url response or another server-issued source.
39
+ * Server returns 400 Bad Request (title `Invalid Signature`) if the URL has
40
+ * been tampered with or has expired.
41
+ */
42
+ getDownloadUrl(storageKey: string, signed?: {
43
+ expires: string;
44
+ sig: string;
45
+ }): string;
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") — `/`
50
+ * is preserved as a path delimiter; other special characters are percent-encoded.
51
+ */
52
+ delete(storageKey: string): Promise<void>;
53
+ /**
54
+ * Convenience method: create upload URL then immediately upload the file.
55
+ * Equivalent to calling createUploadUrl() + upload() in sequence.
56
+ * onProgress is forwarded to the upload step.
57
+ */
58
+ uploadFile(file: File, onProgress?: UploadProgressCallback): Promise<UploadResponse>;
59
+ }
60
+ //# 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;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GACxC,MAAM;IAOT;;;;;OAKG;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,91 @@
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
+ *
41
+ * Default download is public — no auth required:
42
+ * getDownloadUrl("01HXABCDEF/photo.jpg")
43
+ * → "{baseUrl}/api/files/01HXABCDEF/photo.jpg"
44
+ *
45
+ * Pass `signed` to build a signed URL (spec §8.3) when the server enforces
46
+ * controlled access. Both `expires` and `sig` must be supplied — typically
47
+ * forwarded from the upload-url response or another server-issued source.
48
+ * Server returns 400 Bad Request (title `Invalid Signature`) if the URL has
49
+ * been tampered with or has expired.
50
+ */
51
+ getDownloadUrl(storageKey, signed) {
52
+ const path = `/api/files/${encodeStorageKeyPath(storageKey)}`;
53
+ if (!signed)
54
+ return `${this.http.baseUrl}${path}`;
55
+ const qs = new URLSearchParams({ expires: signed.expires, sig: signed.sig });
56
+ return `${this.http.baseUrl}${path}?${qs.toString()}`;
57
+ }
58
+ /**
59
+ * DELETE /api/files/{storageKey}
60
+ * Delete an uploaded file. Only the uploader can delete.
61
+ * storageKey may contain path separators (e.g. "01HXABCDEF/photo.jpg") — `/`
62
+ * is preserved as a path delimiter; other special characters are percent-encoded.
63
+ */
64
+ delete(storageKey) {
65
+ return this.http.delete(`/api/files/${encodeStorageKeyPath(storageKey)}`);
66
+ }
67
+ /**
68
+ * Convenience method: create upload URL then immediately upload the file.
69
+ * Equivalent to calling createUploadUrl() + upload() in sequence.
70
+ * onProgress is forwarded to the upload step.
71
+ */
72
+ async uploadFile(file, onProgress) {
73
+ const { uploadUrl } = await this.createUploadUrl({
74
+ fileName: file.name,
75
+ contentType: file.type,
76
+ fileSize: file.size,
77
+ });
78
+ return this.upload(uploadUrl, file, onProgress);
79
+ }
80
+ }
81
+ /**
82
+ * Percent-encode each segment of a storage key while preserving `/` as the
83
+ * path separator. The server's catch-all route accepts the unencoded key it
84
+ * generated, but a key containing characters like spaces, `?`, `#`, or `%`
85
+ * would otherwise corrupt the URL. Pure pass-through (the previous behaviour)
86
+ * is preserved for the common case where keys are ULID/filename-safe.
87
+ */
88
+ function encodeStorageKeyPath(storageKey) {
89
+ return storageKey.split('/').map(encodeURIComponent).join('/');
90
+ }
91
+ //# 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;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,UAAkB,EAClB,MAAyC;QAEzC,MAAM,IAAI,GAAG,cAAc,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,MAAM;YAAE,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QAClD,MAAM,EAAE,GAAG,IAAI,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAC7E,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;IACxD,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,UAAkB;QACvB,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAO,cAAc,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAClF,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;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,UAAkB;IAC9C,OAAO,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { HttpClient } from './HttpClient.js';
2
+ /**
3
+ * Health check API client.
4
+ * All endpoints are public — no JWT required.
5
+ *
6
+ * Both endpoints return `text/plain` ("Healthy" / "Degraded" / "Unhealthy"),
7
+ * NOT JSON — the server uses ASP.NET Health Checks' default ResponseWriter.
8
+ */
9
+ export declare class HealthApi {
10
+ private readonly http;
11
+ constructor(http: HttpClient);
12
+ /**
13
+ * GET /health/live
14
+ * Liveness probe — returns the plain text string "Healthy" when the server is up.
15
+ */
16
+ live(): Promise<string>;
17
+ /**
18
+ * GET /health/ready
19
+ * Readiness probe — returns plain text "Healthy" / "Degraded" / "Unhealthy".
20
+ * HTTP status: 200 when Healthy/Degraded, 503 when Unhealthy.
21
+ *
22
+ * Note: the gateway is stateless and registers no checks tagged `ready`, so
23
+ * this currently always returns "Healthy". Call the backend's own
24
+ * `/health/ready` if you need infrastructure readiness.
25
+ */
26
+ ready(): Promise<string>;
27
+ }
28
+ //# 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;AAE7C;;;;;;GAMG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,IAAI,EAAE,UAAU;IAI5B;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvB;;;;;;;;OAQG;IACH,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAGzB"}
@@ -0,0 +1,34 @@
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
+ * Both endpoints return `text/plain` ("Healthy" / "Degraded" / "Unhealthy"),
8
+ * NOT JSON — the server uses ASP.NET Health Checks' default ResponseWriter.
9
+ */
10
+ export class HealthApi {
11
+ constructor(http) {
12
+ this.http = http;
13
+ }
14
+ /**
15
+ * GET /health/live
16
+ * Liveness probe — returns the plain text string "Healthy" when the server is up.
17
+ */
18
+ live() {
19
+ return this.http.getText('/health/live');
20
+ }
21
+ /**
22
+ * GET /health/ready
23
+ * Readiness probe — returns plain text "Healthy" / "Degraded" / "Unhealthy".
24
+ * HTTP status: 200 when Healthy/Degraded, 503 when Unhealthy.
25
+ *
26
+ * Note: the gateway is stateless and registers no checks tagged `ready`, so
27
+ * this currently always returns "Healthy". Call the backend's own
28
+ * `/health/ready` if you need infrastructure readiness.
29
+ */
30
+ ready() {
31
+ return this.http.getText('/health/ready');
32
+ }
33
+ }
34
+ //# 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;AAE7C;;;;;;GAMG;AACH,MAAM,OAAO,SAAS;IAGpB,YAAY,IAAgB;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK;QACH,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -0,0 +1,69 @@
1
+ import type { UploadProgressCallback } from '../types/common.js';
2
+ /** Default per-request timeout (ms) when none is supplied. */
3
+ export declare const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
4
+ export interface HttpClientOptions {
5
+ baseUrl: string;
6
+ /** Returns the current JWT token, or null if not authenticated */
7
+ tokenProvider?: () => string | null;
8
+ /**
9
+ * Per-request timeout in milliseconds. Default 30000.
10
+ * Pass `null` to disable the timeout (uploads of large files may need this).
11
+ */
12
+ requestTimeoutMs?: number | null;
13
+ }
14
+ /**
15
+ * Base HTTP client wrapping the Fetch API.
16
+ *
17
+ * Features:
18
+ * - Automatic Authorization: Bearer token injection via tokenProvider
19
+ * - JSON request/response serialization
20
+ * - Throws ChatApiError on non-OK responses
21
+ * - Handles empty responses (204 No Content, 200 with no body) — the SDK
22
+ * convention is to type T as `null` or `void` for empty-body endpoints
23
+ * - Multipart file upload with optional XHR-based upload progress
24
+ * - Per-request timeout via AbortController (configurable, default 30s)
25
+ */
26
+ export declare class HttpClient {
27
+ readonly baseUrl: string;
28
+ private readonly tokenProvider;
29
+ private readonly requestTimeoutMs;
30
+ constructor(options: HttpClientOptions);
31
+ private buildUrl;
32
+ private buildHeaders;
33
+ private buildAuthHeader;
34
+ /**
35
+ * Parse response body safely.
36
+ * Returns null for 204 No Content or empty bodies.
37
+ * Wraps JSON parse failures in ChatApiError for consistency with the XHR path.
38
+ */
39
+ private parseBody;
40
+ private handleResponse;
41
+ /**
42
+ * Run a fetch with an AbortController-based timeout.
43
+ * Throws ChatApiError(0, 'Timeout', ...) when the timeout fires before the
44
+ * response arrives. If `requestTimeoutMs` is null, fetch is used directly.
45
+ */
46
+ private fetchWithTimeout;
47
+ get<T>(path: string, headers?: Record<string, string>): Promise<T>;
48
+ /**
49
+ * GET a plain-text response (e.g. /health/live which returns "Healthy").
50
+ * Unlike get<T>(), this does not attempt JSON parsing.
51
+ */
52
+ getText(path: string): Promise<string>;
53
+ post<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
54
+ patch<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
55
+ put<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
56
+ delete<T>(path: string, body?: unknown, headers?: Record<string, string>): Promise<T>;
57
+ /**
58
+ * POST with multipart/form-data — no explicit Content-Type header
59
+ * (browser sets it with the boundary automatically).
60
+ */
61
+ postFormData<T>(path: string, formData: FormData): Promise<T>;
62
+ /**
63
+ * POST with multipart/form-data and upload progress reporting.
64
+ * Uses XMLHttpRequest instead of fetch because fetch does not support
65
+ * upload progress events.
66
+ */
67
+ postFormDataWithProgress<T>(path: string, formData: FormData, onProgress?: UploadProgressCallback): Promise<T>;
68
+ }
69
+ //# 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,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACpC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsB;IACpD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAgB;gBAErC,OAAO,EAAE,iBAAiB;IAYtC,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,eAAe;IAQvB;;;;OAIG;YACW,SAAS;YAaT,cAAc;IAW5B;;;;OAIG;YACW,gBAAgB;IA6BxB,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,GAAG,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;IASlF,MAAM,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;IAW3F;;;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;CA2Dd"}