@uploadista/client-core 0.0.3

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 (235) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +100 -0
  4. package/dist/auth/auth-http-client.d.ts +50 -0
  5. package/dist/auth/auth-http-client.d.ts.map +1 -0
  6. package/dist/auth/auth-http-client.js +110 -0
  7. package/dist/auth/direct-auth.d.ts +38 -0
  8. package/dist/auth/direct-auth.d.ts.map +1 -0
  9. package/dist/auth/direct-auth.js +95 -0
  10. package/dist/auth/index.d.ts +6 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +5 -0
  13. package/dist/auth/no-auth.d.ts +26 -0
  14. package/dist/auth/no-auth.d.ts.map +1 -0
  15. package/dist/auth/no-auth.js +33 -0
  16. package/dist/auth/saas-auth.d.ts +80 -0
  17. package/dist/auth/saas-auth.d.ts.map +1 -0
  18. package/dist/auth/saas-auth.js +167 -0
  19. package/dist/auth/types.d.ts +101 -0
  20. package/dist/auth/types.d.ts.map +1 -0
  21. package/dist/auth/types.js +8 -0
  22. package/dist/chunk-buffer.d.ts +209 -0
  23. package/dist/chunk-buffer.d.ts.map +1 -0
  24. package/dist/chunk-buffer.js +236 -0
  25. package/dist/client/create-uploadista-client.d.ts +369 -0
  26. package/dist/client/create-uploadista-client.d.ts.map +1 -0
  27. package/dist/client/create-uploadista-client.js +518 -0
  28. package/dist/client/index.d.ts +4 -0
  29. package/dist/client/index.d.ts.map +1 -0
  30. package/dist/client/index.js +3 -0
  31. package/dist/client/uploadista-api.d.ts +284 -0
  32. package/dist/client/uploadista-api.d.ts.map +1 -0
  33. package/dist/client/uploadista-api.js +444 -0
  34. package/dist/client/uploadista-websocket-manager.d.ts +110 -0
  35. package/dist/client/uploadista-websocket-manager.d.ts.map +1 -0
  36. package/dist/client/uploadista-websocket-manager.js +207 -0
  37. package/dist/error.d.ts +106 -0
  38. package/dist/error.d.ts.map +1 -0
  39. package/dist/error.js +69 -0
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +12 -0
  43. package/dist/logger.d.ts +70 -0
  44. package/dist/logger.d.ts.map +1 -0
  45. package/dist/logger.js +59 -0
  46. package/dist/mock-data-store.d.ts +30 -0
  47. package/dist/mock-data-store.d.ts.map +1 -0
  48. package/dist/mock-data-store.js +88 -0
  49. package/dist/network-monitor.d.ts +262 -0
  50. package/dist/network-monitor.d.ts.map +1 -0
  51. package/dist/network-monitor.js +291 -0
  52. package/dist/services/abort-controller-service.d.ts +19 -0
  53. package/dist/services/abort-controller-service.d.ts.map +1 -0
  54. package/dist/services/abort-controller-service.js +4 -0
  55. package/dist/services/checksum-service.d.ts +4 -0
  56. package/dist/services/checksum-service.d.ts.map +1 -0
  57. package/dist/services/checksum-service.js +1 -0
  58. package/dist/services/file-reader-service.d.ts +38 -0
  59. package/dist/services/file-reader-service.d.ts.map +1 -0
  60. package/dist/services/file-reader-service.js +4 -0
  61. package/dist/services/fingerprint-service.d.ts +4 -0
  62. package/dist/services/fingerprint-service.d.ts.map +1 -0
  63. package/dist/services/fingerprint-service.js +1 -0
  64. package/dist/services/http-client.d.ts +182 -0
  65. package/dist/services/http-client.d.ts.map +1 -0
  66. package/dist/services/http-client.js +1 -0
  67. package/dist/services/id-generation-service.d.ts +10 -0
  68. package/dist/services/id-generation-service.d.ts.map +1 -0
  69. package/dist/services/id-generation-service.js +1 -0
  70. package/dist/services/index.d.ts +11 -0
  71. package/dist/services/index.d.ts.map +1 -0
  72. package/dist/services/index.js +10 -0
  73. package/dist/services/platform-service.d.ts +48 -0
  74. package/dist/services/platform-service.d.ts.map +1 -0
  75. package/dist/services/platform-service.js +10 -0
  76. package/dist/services/service-container.d.ts +25 -0
  77. package/dist/services/service-container.d.ts.map +1 -0
  78. package/dist/services/service-container.js +1 -0
  79. package/dist/services/storage-service.d.ts +26 -0
  80. package/dist/services/storage-service.d.ts.map +1 -0
  81. package/dist/services/storage-service.js +1 -0
  82. package/dist/services/websocket-service.d.ts +36 -0
  83. package/dist/services/websocket-service.d.ts.map +1 -0
  84. package/dist/services/websocket-service.js +4 -0
  85. package/dist/smart-chunker.d.ts +72 -0
  86. package/dist/smart-chunker.d.ts.map +1 -0
  87. package/dist/smart-chunker.js +317 -0
  88. package/dist/storage/client-storage.d.ts +148 -0
  89. package/dist/storage/client-storage.d.ts.map +1 -0
  90. package/dist/storage/client-storage.js +62 -0
  91. package/dist/storage/in-memory-storage-service.d.ts +7 -0
  92. package/dist/storage/in-memory-storage-service.d.ts.map +1 -0
  93. package/dist/storage/in-memory-storage-service.js +24 -0
  94. package/dist/storage/index.d.ts +3 -0
  95. package/dist/storage/index.d.ts.map +1 -0
  96. package/dist/storage/index.js +2 -0
  97. package/dist/types/buffered-chunk.d.ts +6 -0
  98. package/dist/types/buffered-chunk.d.ts.map +1 -0
  99. package/dist/types/buffered-chunk.js +1 -0
  100. package/dist/types/chunk-metrics.d.ts +12 -0
  101. package/dist/types/chunk-metrics.d.ts.map +1 -0
  102. package/dist/types/chunk-metrics.js +1 -0
  103. package/dist/types/flow-result.d.ts +11 -0
  104. package/dist/types/flow-result.d.ts.map +1 -0
  105. package/dist/types/flow-result.js +1 -0
  106. package/dist/types/flow-upload-config.d.ts +54 -0
  107. package/dist/types/flow-upload-config.d.ts.map +1 -0
  108. package/dist/types/flow-upload-config.js +1 -0
  109. package/dist/types/flow-upload-item.d.ts +16 -0
  110. package/dist/types/flow-upload-item.d.ts.map +1 -0
  111. package/dist/types/flow-upload-item.js +1 -0
  112. package/dist/types/flow-upload-options.d.ts +41 -0
  113. package/dist/types/flow-upload-options.d.ts.map +1 -0
  114. package/dist/types/flow-upload-options.js +1 -0
  115. package/dist/types/index.d.ts +14 -0
  116. package/dist/types/index.d.ts.map +1 -0
  117. package/dist/types/index.js +13 -0
  118. package/dist/types/multi-flow-upload-options.d.ts +33 -0
  119. package/dist/types/multi-flow-upload-options.d.ts.map +1 -0
  120. package/dist/types/multi-flow-upload-options.js +1 -0
  121. package/dist/types/multi-flow-upload-state.d.ts +9 -0
  122. package/dist/types/multi-flow-upload-state.d.ts.map +1 -0
  123. package/dist/types/multi-flow-upload-state.js +1 -0
  124. package/dist/types/performance-insights.d.ts +11 -0
  125. package/dist/types/performance-insights.d.ts.map +1 -0
  126. package/dist/types/performance-insights.js +1 -0
  127. package/dist/types/previous-upload.d.ts +20 -0
  128. package/dist/types/previous-upload.d.ts.map +1 -0
  129. package/dist/types/previous-upload.js +9 -0
  130. package/dist/types/upload-options.d.ts +40 -0
  131. package/dist/types/upload-options.d.ts.map +1 -0
  132. package/dist/types/upload-options.js +1 -0
  133. package/dist/types/upload-response.d.ts +6 -0
  134. package/dist/types/upload-response.d.ts.map +1 -0
  135. package/dist/types/upload-response.js +1 -0
  136. package/dist/types/upload-result.d.ts +57 -0
  137. package/dist/types/upload-result.d.ts.map +1 -0
  138. package/dist/types/upload-result.js +1 -0
  139. package/dist/types/upload-session-metrics.d.ts +16 -0
  140. package/dist/types/upload-session-metrics.d.ts.map +1 -0
  141. package/dist/types/upload-session-metrics.js +1 -0
  142. package/dist/upload/chunk-upload.d.ts +40 -0
  143. package/dist/upload/chunk-upload.d.ts.map +1 -0
  144. package/dist/upload/chunk-upload.js +82 -0
  145. package/dist/upload/flow-upload.d.ts +48 -0
  146. package/dist/upload/flow-upload.d.ts.map +1 -0
  147. package/dist/upload/flow-upload.js +240 -0
  148. package/dist/upload/index.d.ts +3 -0
  149. package/dist/upload/index.d.ts.map +1 -0
  150. package/dist/upload/index.js +2 -0
  151. package/dist/upload/parallel-upload.d.ts +65 -0
  152. package/dist/upload/parallel-upload.d.ts.map +1 -0
  153. package/dist/upload/parallel-upload.js +231 -0
  154. package/dist/upload/single-upload.d.ts +118 -0
  155. package/dist/upload/single-upload.d.ts.map +1 -0
  156. package/dist/upload/single-upload.js +332 -0
  157. package/dist/upload/upload-manager.d.ts +30 -0
  158. package/dist/upload/upload-manager.d.ts.map +1 -0
  159. package/dist/upload/upload-manager.js +57 -0
  160. package/dist/upload/upload-metrics.d.ts +37 -0
  161. package/dist/upload/upload-metrics.d.ts.map +1 -0
  162. package/dist/upload/upload-metrics.js +236 -0
  163. package/dist/upload/upload-storage.d.ts +32 -0
  164. package/dist/upload/upload-storage.d.ts.map +1 -0
  165. package/dist/upload/upload-storage.js +46 -0
  166. package/dist/upload/upload-strategy.d.ts +66 -0
  167. package/dist/upload/upload-strategy.d.ts.map +1 -0
  168. package/dist/upload/upload-strategy.js +171 -0
  169. package/dist/upload/upload-utils.d.ts +26 -0
  170. package/dist/upload/upload-utils.d.ts.map +1 -0
  171. package/dist/upload/upload-utils.js +80 -0
  172. package/package.json +29 -0
  173. package/src/__tests__/smart-chunking.test.ts +399 -0
  174. package/src/auth/__tests__/auth-http-client.test.ts +327 -0
  175. package/src/auth/__tests__/direct-auth.test.ts +135 -0
  176. package/src/auth/__tests__/no-auth.test.ts +40 -0
  177. package/src/auth/__tests__/saas-auth.test.ts +337 -0
  178. package/src/auth/auth-http-client.ts +150 -0
  179. package/src/auth/direct-auth.ts +121 -0
  180. package/src/auth/index.ts +5 -0
  181. package/src/auth/no-auth.ts +39 -0
  182. package/src/auth/saas-auth.ts +218 -0
  183. package/src/auth/types.ts +105 -0
  184. package/src/chunk-buffer.ts +287 -0
  185. package/src/client/create-uploadista-client.ts +901 -0
  186. package/src/client/index.ts +3 -0
  187. package/src/client/uploadista-api.ts +857 -0
  188. package/src/client/uploadista-websocket-manager.ts +275 -0
  189. package/src/error.ts +149 -0
  190. package/src/index.ts +13 -0
  191. package/src/logger.ts +104 -0
  192. package/src/mock-data-store.ts +97 -0
  193. package/src/network-monitor.ts +445 -0
  194. package/src/services/abort-controller-service.ts +21 -0
  195. package/src/services/checksum-service.ts +3 -0
  196. package/src/services/file-reader-service.ts +44 -0
  197. package/src/services/fingerprint-service.ts +6 -0
  198. package/src/services/http-client.ts +229 -0
  199. package/src/services/id-generation-service.ts +9 -0
  200. package/src/services/index.ts +10 -0
  201. package/src/services/platform-service.ts +65 -0
  202. package/src/services/service-container.ts +24 -0
  203. package/src/services/storage-service.ts +29 -0
  204. package/src/services/websocket-service.ts +33 -0
  205. package/src/smart-chunker.ts +451 -0
  206. package/src/storage/client-storage.ts +186 -0
  207. package/src/storage/in-memory-storage-service.ts +33 -0
  208. package/src/storage/index.ts +2 -0
  209. package/src/types/buffered-chunk.ts +5 -0
  210. package/src/types/chunk-metrics.ts +11 -0
  211. package/src/types/flow-result.ts +14 -0
  212. package/src/types/flow-upload-config.ts +56 -0
  213. package/src/types/flow-upload-item.ts +16 -0
  214. package/src/types/flow-upload-options.ts +56 -0
  215. package/src/types/index.ts +13 -0
  216. package/src/types/multi-flow-upload-options.ts +39 -0
  217. package/src/types/multi-flow-upload-state.ts +9 -0
  218. package/src/types/performance-insights.ts +7 -0
  219. package/src/types/previous-upload.ts +22 -0
  220. package/src/types/upload-options.ts +56 -0
  221. package/src/types/upload-response.ts +6 -0
  222. package/src/types/upload-result.ts +60 -0
  223. package/src/types/upload-session-metrics.ts +15 -0
  224. package/src/upload/chunk-upload.ts +151 -0
  225. package/src/upload/flow-upload.ts +367 -0
  226. package/src/upload/index.ts +2 -0
  227. package/src/upload/parallel-upload.ts +387 -0
  228. package/src/upload/single-upload.ts +554 -0
  229. package/src/upload/upload-manager.ts +106 -0
  230. package/src/upload/upload-metrics.ts +340 -0
  231. package/src/upload/upload-storage.ts +87 -0
  232. package/src/upload/upload-strategy.ts +296 -0
  233. package/src/upload/upload-utils.ts +114 -0
  234. package/tsconfig.json +23 -0
  235. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,327 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import type { HttpClient } from "../../http-client";
3
+ import { AuthHttpClient } from "../auth-http-client";
4
+ import { DirectAuthManager } from "../direct-auth";
5
+ import { NoAuthManager } from "../no-auth";
6
+ import { SaasAuthManager } from "../saas-auth";
7
+ import type { DirectAuthConfig, SaasAuthConfig } from "../types";
8
+
9
+ // Mock fetch globally
10
+ global.fetch = vi.fn();
11
+
12
+ describe("AuthHttpClient", () => {
13
+ let mockHttpClient: HttpClient;
14
+
15
+ beforeEach(() => {
16
+ vi.clearAllMocks();
17
+
18
+ // Create mock HTTP client
19
+ mockHttpClient = {
20
+ request: vi.fn(async () => ({
21
+ status: 200,
22
+ statusText: "OK",
23
+ headers: new Headers(),
24
+ ok: true,
25
+ json: async () => ({}),
26
+ text: async () => "",
27
+ arrayBuffer: async () => new ArrayBuffer(0),
28
+ })),
29
+ getMetrics: vi.fn(() => ({
30
+ activeConnections: 0,
31
+ totalConnections: 0,
32
+ reuseRate: 0,
33
+ averageConnectionTime: 0,
34
+ })),
35
+ getDetailedMetrics: vi.fn(() => ({
36
+ activeConnections: 0,
37
+ totalConnections: 0,
38
+ reuseRate: 0,
39
+ averageConnectionTime: 0,
40
+ health: {
41
+ status: "healthy" as const,
42
+ score: 100,
43
+ issues: [],
44
+ recommendations: [],
45
+ },
46
+ requestsPerSecond: 0,
47
+ errorRate: 0,
48
+ timeouts: 0,
49
+ retries: 0,
50
+ fastConnections: 0,
51
+ slowConnections: 0,
52
+ http2Info: {
53
+ supported: true,
54
+ detected: false,
55
+ version: "h2",
56
+ multiplexingActive: false,
57
+ },
58
+ })),
59
+ reset: vi.fn(),
60
+ close: vi.fn(async () => {}),
61
+ warmupConnections: vi.fn(async () => {}),
62
+ };
63
+ });
64
+
65
+ describe("with NoAuthManager", () => {
66
+ it("should pass through requests unchanged", async () => {
67
+ const authManager = new NoAuthManager();
68
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
69
+
70
+ await authClient.request("https://api.example.com/upload", {
71
+ method: "POST",
72
+ headers: { "Content-Type": "application/json" },
73
+ });
74
+
75
+ expect(mockHttpClient.request).toHaveBeenCalledWith(
76
+ "https://api.example.com/upload",
77
+ {
78
+ method: "POST",
79
+ headers: { "Content-Type": "application/json" },
80
+ },
81
+ );
82
+ });
83
+ });
84
+
85
+ describe("with DirectAuthManager", () => {
86
+ it("should attach credentials from DirectAuthManager", async () => {
87
+ const config: DirectAuthConfig = {
88
+ mode: "direct",
89
+ getCredentials: () => ({
90
+ headers: { Authorization: "Bearer direct-token" },
91
+ }),
92
+ };
93
+ const authManager = new DirectAuthManager(config);
94
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
95
+
96
+ await authClient.request("https://api.example.com/upload", {
97
+ method: "POST",
98
+ headers: { "Content-Type": "application/json" },
99
+ });
100
+
101
+ expect(mockHttpClient.request).toHaveBeenCalledWith(
102
+ "https://api.example.com/upload",
103
+ {
104
+ method: "POST",
105
+ headers: {
106
+ "Content-Type": "application/json",
107
+ Authorization: "Bearer direct-token",
108
+ },
109
+ },
110
+ );
111
+ });
112
+
113
+ it("should handle async credentials", async () => {
114
+ const config: DirectAuthConfig = {
115
+ mode: "direct",
116
+ getCredentials: async () => {
117
+ await new Promise((resolve) => setTimeout(resolve, 10));
118
+ return { headers: { Authorization: "Bearer async-token" } };
119
+ },
120
+ };
121
+ const authManager = new DirectAuthManager(config);
122
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
123
+
124
+ await authClient.request("https://api.example.com/upload");
125
+
126
+ expect(mockHttpClient.request).toHaveBeenCalledWith(
127
+ "https://api.example.com/upload",
128
+ {
129
+ headers: { Authorization: "Bearer async-token" },
130
+ },
131
+ );
132
+ });
133
+ });
134
+
135
+ describe("with SaasAuthManager", () => {
136
+ it("should attach JWT token from SaasAuthManager", async () => {
137
+ const config: SaasAuthConfig = {
138
+ mode: "saas",
139
+ authServerUrl: "https://auth.example.com/token",
140
+ getCredentials: () => ({ username: "user", password: "pass" }),
141
+ };
142
+
143
+ vi.mocked(global.fetch).mockResolvedValueOnce({
144
+ ok: true,
145
+ json: async () => ({ token: "jwt-token-123" }),
146
+ } as Response);
147
+
148
+ const authManager = new SaasAuthManager(config);
149
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
150
+
151
+ await authClient.request("https://api.example.com/upload", {
152
+ method: "POST",
153
+ headers: { "Content-Type": "application/json" },
154
+ });
155
+
156
+ expect(mockHttpClient.request).toHaveBeenCalledWith(
157
+ "https://api.example.com/upload",
158
+ {
159
+ method: "POST",
160
+ headers: {
161
+ "Content-Type": "application/json",
162
+ Authorization: "Bearer jwt-token-123",
163
+ },
164
+ },
165
+ );
166
+ });
167
+
168
+ it("should extract job ID from upload URL", async () => {
169
+ const config: SaasAuthConfig = {
170
+ mode: "saas",
171
+ authServerUrl: "https://auth.example.com/token",
172
+ getCredentials: () => ({ username: "user", password: "pass" }),
173
+ };
174
+
175
+ vi.mocked(global.fetch).mockResolvedValueOnce({
176
+ ok: true,
177
+ json: async () => ({ token: "jwt-token-for-upload-123" }),
178
+ } as Response);
179
+
180
+ const authManager = new SaasAuthManager(config);
181
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
182
+
183
+ await authClient.request(
184
+ "https://api.example.com/uploadista/api/upload/upload-123",
185
+ { method: "PATCH" },
186
+ );
187
+
188
+ // Token should be cached for upload-123
189
+ const stats = authManager.getCacheStats();
190
+ expect(stats.cachedJobCount).toBe(1);
191
+ });
192
+
193
+ it("should extract job ID from flow URL", async () => {
194
+ const config: SaasAuthConfig = {
195
+ mode: "saas",
196
+ authServerUrl: "https://auth.example.com/token",
197
+ getCredentials: () => ({ username: "user", password: "pass" }),
198
+ };
199
+
200
+ vi.mocked(global.fetch).mockResolvedValueOnce({
201
+ ok: true,
202
+ json: async () => ({ token: "jwt-token-for-flow-456" }),
203
+ } as Response);
204
+
205
+ const authManager = new SaasAuthManager(config);
206
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
207
+
208
+ await authClient.request(
209
+ "https://api.example.com/uploadista/api/flow/flow-456/storage-id",
210
+ { method: "POST" },
211
+ );
212
+
213
+ // Token should be cached for flow-456
214
+ const stats = authManager.getCacheStats();
215
+ expect(stats.cachedJobCount).toBe(1);
216
+ });
217
+
218
+ it("should extract job ID from jobs URL", async () => {
219
+ const config: SaasAuthConfig = {
220
+ mode: "saas",
221
+ authServerUrl: "https://auth.example.com/token",
222
+ getCredentials: () => ({ username: "user", password: "pass" }),
223
+ };
224
+
225
+ vi.mocked(global.fetch).mockResolvedValueOnce({
226
+ ok: true,
227
+ json: async () => ({ token: "jwt-token-for-job-789" }),
228
+ } as Response);
229
+
230
+ const authManager = new SaasAuthManager(config);
231
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
232
+
233
+ await authClient.request(
234
+ "https://api.example.com/uploadista/api/jobs/job-789/status",
235
+ { method: "GET" },
236
+ );
237
+
238
+ // Token should be cached for job-789
239
+ const stats = authManager.getCacheStats();
240
+ expect(stats.cachedJobCount).toBe(1);
241
+ });
242
+ });
243
+
244
+ describe("error handling", () => {
245
+ it("should propagate auth errors", async () => {
246
+ const config: DirectAuthConfig = {
247
+ mode: "direct",
248
+ getCredentials: () => {
249
+ throw new Error("Failed to get auth credentials");
250
+ },
251
+ };
252
+
253
+ const authManager = new DirectAuthManager(config);
254
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
255
+
256
+ await expect(
257
+ authClient.request("https://api.example.com/upload"),
258
+ ).rejects.toThrow("Failed to attach auth credentials");
259
+ });
260
+
261
+ it("should propagate HTTP client errors", async () => {
262
+ const authManager = new NoAuthManager();
263
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
264
+
265
+ vi.mocked(mockHttpClient.request).mockRejectedValueOnce(
266
+ new Error("Network error"),
267
+ );
268
+
269
+ await expect(
270
+ authClient.request("https://api.example.com/upload"),
271
+ ).rejects.toThrow("Network error");
272
+ });
273
+ });
274
+
275
+ describe("delegation methods", () => {
276
+ it("should delegate getMetrics", () => {
277
+ const authManager = new NoAuthManager();
278
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
279
+
280
+ authClient.getMetrics();
281
+ expect(mockHttpClient.getMetrics).toHaveBeenCalled();
282
+ });
283
+
284
+ it("should delegate getDetailedMetrics", () => {
285
+ const authManager = new NoAuthManager();
286
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
287
+
288
+ authClient.getDetailedMetrics();
289
+ expect(mockHttpClient.getDetailedMetrics).toHaveBeenCalled();
290
+ });
291
+
292
+ it("should delegate reset", () => {
293
+ const authManager = new NoAuthManager();
294
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
295
+
296
+ authClient.reset();
297
+ expect(mockHttpClient.reset).toHaveBeenCalled();
298
+ });
299
+
300
+ it("should delegate close", async () => {
301
+ const authManager = new NoAuthManager();
302
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
303
+
304
+ await authClient.close();
305
+ expect(mockHttpClient.close).toHaveBeenCalled();
306
+ });
307
+
308
+ it("should delegate warmupConnections", async () => {
309
+ const authManager = new NoAuthManager();
310
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
311
+
312
+ await authClient.warmupConnections(["https://api.example.com"]);
313
+ expect(mockHttpClient.warmupConnections).toHaveBeenCalledWith([
314
+ "https://api.example.com",
315
+ ]);
316
+ });
317
+ });
318
+
319
+ describe("getAuthManager", () => {
320
+ it("should return the auth manager", () => {
321
+ const authManager = new NoAuthManager();
322
+ const authClient = new AuthHttpClient(mockHttpClient, authManager);
323
+
324
+ expect(authClient.getAuthManager()).toBe(authManager);
325
+ });
326
+ });
327
+ });
@@ -0,0 +1,135 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { DirectAuthManager } from "../direct-auth";
3
+ import type { DirectAuthConfig } from "../types";
4
+
5
+ describe("DirectAuthManager", () => {
6
+ describe("attachCredentials", () => {
7
+ it("should attach headers from getCredentials", async () => {
8
+ const config: DirectAuthConfig = {
9
+ mode: "direct",
10
+ getCredentials: () => ({
11
+ headers: {
12
+ Authorization: "Bearer test-token",
13
+ "X-API-Key": "api-key-123",
14
+ },
15
+ }),
16
+ };
17
+
18
+ const manager = new DirectAuthManager(config);
19
+ const result = await manager.attachCredentials({
20
+ "Content-Type": "application/json",
21
+ });
22
+
23
+ expect(result).toEqual({
24
+ "Content-Type": "application/json",
25
+ Authorization: "Bearer test-token",
26
+ "X-API-Key": "api-key-123",
27
+ });
28
+ });
29
+
30
+ it("should support async getCredentials", async () => {
31
+ const config: DirectAuthConfig = {
32
+ mode: "direct",
33
+ getCredentials: async () => {
34
+ // Simulate async token fetch
35
+ await new Promise((resolve) => setTimeout(resolve, 10));
36
+ return {
37
+ headers: {
38
+ Authorization: "Bearer async-token",
39
+ },
40
+ };
41
+ },
42
+ };
43
+
44
+ const manager = new DirectAuthManager(config);
45
+ const result = await manager.attachCredentials();
46
+
47
+ expect(result).toEqual({
48
+ Authorization: "Bearer async-token",
49
+ });
50
+ });
51
+
52
+ it("should handle empty credentials gracefully", async () => {
53
+ const config: DirectAuthConfig = {
54
+ mode: "direct",
55
+ getCredentials: () => ({}),
56
+ };
57
+
58
+ const manager = new DirectAuthManager(config);
59
+ const result = await manager.attachCredentials({
60
+ "Content-Type": "application/json",
61
+ });
62
+
63
+ expect(result).toEqual({
64
+ "Content-Type": "application/json",
65
+ });
66
+ });
67
+
68
+ it("should override existing headers with credential headers", async () => {
69
+ const config: DirectAuthConfig = {
70
+ mode: "direct",
71
+ getCredentials: () => ({
72
+ headers: {
73
+ Authorization: "Bearer new-token",
74
+ },
75
+ }),
76
+ };
77
+
78
+ const manager = new DirectAuthManager(config);
79
+ const result = await manager.attachCredentials({
80
+ Authorization: "Bearer old-token",
81
+ "Content-Type": "application/json",
82
+ });
83
+
84
+ expect(result).toEqual({
85
+ Authorization: "Bearer new-token",
86
+ "Content-Type": "application/json",
87
+ });
88
+ });
89
+
90
+ it("should throw error if getCredentials returns non-object", async () => {
91
+ const config: DirectAuthConfig = {
92
+ mode: "direct",
93
+ getCredentials: () => null as any,
94
+ };
95
+
96
+ const manager = new DirectAuthManager(config);
97
+
98
+ await expect(manager.attachCredentials()).rejects.toThrow(
99
+ "Failed to attach auth credentials",
100
+ );
101
+ });
102
+
103
+ it("should throw error if getCredentials throws", async () => {
104
+ const config: DirectAuthConfig = {
105
+ mode: "direct",
106
+ getCredentials: () => {
107
+ throw new Error("Token fetch failed");
108
+ },
109
+ };
110
+
111
+ const manager = new DirectAuthManager(config);
112
+
113
+ await expect(manager.attachCredentials()).rejects.toThrow(
114
+ "Failed to attach auth credentials: Token fetch failed",
115
+ );
116
+ });
117
+
118
+ it("should validate header types", async () => {
119
+ const config: DirectAuthConfig = {
120
+ mode: "direct",
121
+ getCredentials: () => ({
122
+ headers: {
123
+ Authorization: 123 as any, // Invalid: number instead of string
124
+ },
125
+ }),
126
+ };
127
+
128
+ const manager = new DirectAuthManager(config);
129
+
130
+ await expect(manager.attachCredentials()).rejects.toThrow(
131
+ "Invalid header",
132
+ );
133
+ });
134
+ });
135
+ });
@@ -0,0 +1,40 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { NoAuthManager } from "../no-auth";
3
+
4
+ describe("NoAuthManager", () => {
5
+ describe("attachCredentials", () => {
6
+ it("should return headers unchanged", async () => {
7
+ const manager = new NoAuthManager();
8
+ const headers = {
9
+ "Content-Type": "application/json",
10
+ Accept: "application/json",
11
+ };
12
+
13
+ const result = await manager.attachCredentials(headers);
14
+
15
+ expect(result).toEqual(headers);
16
+ expect(result).toBe(headers); // Should be same object
17
+ });
18
+
19
+ it("should handle empty headers", async () => {
20
+ const manager = new NoAuthManager();
21
+ const result = await manager.attachCredentials();
22
+
23
+ expect(result).toEqual({});
24
+ });
25
+ });
26
+
27
+ describe("clearToken", () => {
28
+ it("should be a no-op", () => {
29
+ const manager = new NoAuthManager();
30
+ expect(() => manager.clearToken("job-1")).not.toThrow();
31
+ });
32
+ });
33
+
34
+ describe("clearAllTokens", () => {
35
+ it("should be a no-op", () => {
36
+ const manager = new NoAuthManager();
37
+ expect(() => manager.clearAllTokens()).not.toThrow();
38
+ });
39
+ });
40
+ });