@ai-sdk/amazon-bedrock 4.0.27 → 4.0.29

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 (39) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/anthropic/index.js +1 -1
  3. package/dist/anthropic/index.mjs +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/package.json +9 -5
  7. package/src/__fixtures__/bedrock-json-only-text-first.1.chunks.txt +0 -7
  8. package/src/__fixtures__/bedrock-json-other-tool.1.chunks.txt +0 -6
  9. package/src/__fixtures__/bedrock-json-other-tool.1.json +0 -24
  10. package/src/__fixtures__/bedrock-json-tool-text-then-weather-then-json.1.chunks.txt +0 -12
  11. package/src/__fixtures__/bedrock-json-tool-with-answer.1.json +0 -29
  12. package/src/__fixtures__/bedrock-json-tool.1.chunks.txt +0 -4
  13. package/src/__fixtures__/bedrock-json-tool.1.json +0 -35
  14. package/src/__fixtures__/bedrock-json-tool.2.chunks.txt +0 -6
  15. package/src/__fixtures__/bedrock-json-tool.2.json +0 -28
  16. package/src/__fixtures__/bedrock-json-tool.3.chunks.txt +0 -7
  17. package/src/__fixtures__/bedrock-json-tool.3.json +0 -36
  18. package/src/__fixtures__/bedrock-json-with-tool.1.chunks.txt +0 -9
  19. package/src/__fixtures__/bedrock-json-with-tool.1.json +0 -41
  20. package/src/__fixtures__/bedrock-json-with-tools.1.chunks.txt +0 -12
  21. package/src/__fixtures__/bedrock-json-with-tools.1.json +0 -50
  22. package/src/__fixtures__/bedrock-tool-call.1.chunks.txt +0 -6
  23. package/src/__fixtures__/bedrock-tool-call.1.json +0 -24
  24. package/src/__fixtures__/bedrock-tool-no-args.chunks.txt +0 -8
  25. package/src/__fixtures__/bedrock-tool-no-args.json +0 -25
  26. package/src/anthropic/bedrock-anthropic-fetch.test.ts +0 -344
  27. package/src/anthropic/bedrock-anthropic-provider.test.ts +0 -456
  28. package/src/bedrock-chat-language-model.test.ts +0 -4569
  29. package/src/bedrock-embedding-model.test.ts +0 -148
  30. package/src/bedrock-event-stream-response-handler.test.ts +0 -233
  31. package/src/bedrock-image-model.test.ts +0 -866
  32. package/src/bedrock-provider.test.ts +0 -457
  33. package/src/bedrock-sigv4-fetch.test.ts +0 -675
  34. package/src/convert-bedrock-usage.test.ts +0 -207
  35. package/src/convert-to-bedrock-chat-messages.test.ts +0 -1175
  36. package/src/inject-fetch-headers.test.ts +0 -135
  37. package/src/normalize-tool-call-id.test.ts +0 -72
  38. package/src/reranking/__fixtures__/bedrock-reranking.1.json +0 -12
  39. package/src/reranking/bedrock-reranking-model.test.ts +0 -299
@@ -1,675 +0,0 @@
1
- import {
2
- createSigV4FetchFunction,
3
- createApiKeyFetchFunction,
4
- } from './bedrock-sigv4-fetch';
5
- import { vi, describe, it, expect, afterEach } from 'vitest';
6
-
7
- // Mock the version module
8
- vi.mock('./version', () => ({
9
- VERSION: '0.0.0-test',
10
- }));
11
-
12
- // Mock provider-utils to control runtime environment detection
13
- vi.mock('@ai-sdk/provider-utils', async () => {
14
- const actual = await vi.importActual('@ai-sdk/provider-utils');
15
- return {
16
- ...actual,
17
- getRuntimeEnvironmentUserAgent: vi.fn(() => 'runtime/testenv'),
18
- };
19
- });
20
-
21
- // Mock AwsV4Signer so that no real crypto calls are made.
22
- vi.mock('aws4fetch', () => {
23
- class MockAwsV4Signer {
24
- options: any;
25
- constructor(options: any) {
26
- this.options = options;
27
- }
28
- async sign() {
29
- // Return a fake Headers instance with predetermined signing headers.
30
- const headers = new Headers();
31
- headers.set('x-amz-date', '20240315T000000Z');
32
- headers.set('authorization', 'AWS4-HMAC-SHA256 Credential=test');
33
- if (this.options.sessionToken) {
34
- headers.set('x-amz-security-token', this.options.sessionToken);
35
- }
36
- return { headers };
37
- }
38
- }
39
- return { AwsV4Signer: MockAwsV4Signer };
40
- });
41
-
42
- const createFetchFunction = (dummyFetch: any) =>
43
- createSigV4FetchFunction(
44
- () => ({
45
- region: 'us-west-2',
46
- accessKeyId: 'test-access-key',
47
- secretAccessKey: 'test-secret',
48
- }),
49
- dummyFetch,
50
- );
51
-
52
- describe('createSigV4FetchFunction', () => {
53
- afterEach(() => {
54
- vi.restoreAllMocks();
55
- });
56
-
57
- it('should bypass signing for non-POST requests', async () => {
58
- const dummyResponse = new Response('OK', { status: 200 });
59
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
60
- const fetchFn = createFetchFunction(dummyFetch);
61
-
62
- const response = await fetchFn('http://example.com', { method: 'GET' });
63
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
64
- method: 'GET',
65
- headers: {
66
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
67
- },
68
- });
69
- expect(response).toBe(dummyResponse);
70
- });
71
-
72
- it('should bypass signing if POST request has no body', async () => {
73
- const dummyResponse = new Response('OK', { status: 200 });
74
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
75
- const fetchFn = createFetchFunction(dummyFetch);
76
-
77
- const response = await fetchFn('http://example.com', { method: 'POST' });
78
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
79
- method: 'POST',
80
- headers: {
81
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
82
- },
83
- });
84
- expect(response).toBe(dummyResponse);
85
- });
86
-
87
- it('should handle a POST request with a string body and merge signed headers including user-agent', async () => {
88
- const dummyResponse = new Response('Signed', { status: 200 });
89
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
90
-
91
- // Provide settings (including a sessionToken) so that the signer includes that header.\
92
- const fetchFn = createSigV4FetchFunction(
93
- () => ({
94
- region: 'us-west-2',
95
- accessKeyId: 'test-access-key',
96
- secretAccessKey: 'test-secret',
97
- sessionToken: 'test-session-token',
98
- }),
99
- dummyFetch,
100
- );
101
-
102
- const inputUrl = 'http://example.com';
103
- const init: RequestInit = {
104
- method: 'POST',
105
- body: '{"test": "data"}',
106
- headers: {
107
- 'Content-Type': 'application/json',
108
- 'Custom-Header': 'value',
109
- },
110
- };
111
-
112
- await fetchFn(inputUrl, init);
113
- expect(dummyFetch).toHaveBeenCalled();
114
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
115
- // `combinedHeaders` should merge the original headers with the signing
116
- // headers added by the AwsV4Signer mock.
117
- const headers = calledInit.headers as Record<string, string>;
118
- expect(headers['content-type']).toEqual('application/json');
119
- expect(headers['custom-header']).toEqual('value');
120
- expect(headers['empty-header']).toBeUndefined();
121
- expect(headers['x-amz-date']).toEqual('20240315T000000Z');
122
- expect(headers['authorization']).toEqual(
123
- 'AWS4-HMAC-SHA256 Credential=test',
124
- );
125
- expect(headers['x-amz-security-token']).toEqual('test-session-token');
126
- expect(headers['user-agent']).toEqual(
127
- 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
128
- );
129
- // Body is left unmodified for a string body.
130
- expect(calledInit.body).toEqual('{"test": "data"}');
131
- });
132
-
133
- it('shold handle a POST request with a Request object', async () => {
134
- const dummyResponse = new Response('Signed', { status: 200 });
135
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
136
- const fetchFn = createFetchFunction(dummyFetch);
137
-
138
- const inputUrl = 'http://example.com';
139
- const request = new Request(inputUrl, {
140
- method: 'POST',
141
- body: '{"test": "data"}',
142
- headers: { 'X-From-Request': 'from-request' },
143
- });
144
- const init: RequestInit = {
145
- method: 'POST',
146
- headers: {
147
- 'Content-Type': 'application/json',
148
- 'Custom-Header': 'value',
149
- },
150
- };
151
- await fetchFn(request, init);
152
- expect(dummyFetch).toHaveBeenCalled();
153
- const calledRequest = dummyFetch.mock.calls[0][0] as Request;
154
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
155
- const headers = calledInit.headers as Record<string, string>;
156
- expect(calledRequest.url).toEqual('http://example.com/');
157
- expect(calledInit.body).toEqual('{"test": "data"}');
158
- expect(headers['content-type']).toEqual('application/json');
159
- expect(headers['custom-header']).toEqual('value');
160
- expect(headers['x-from-request']).toEqual('from-request');
161
- });
162
-
163
- it('should sign when input is a POST Request with body and no init', async () => {
164
- const dummyResponse = new Response('Signed', { status: 200 });
165
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
166
- const fetchFn = createFetchFunction(dummyFetch);
167
-
168
- const request = new Request('http://example.com', {
169
- method: 'POST',
170
- body: '{"test": "data"}',
171
- headers: {
172
- 'Content-Type': 'application/json',
173
- 'X-From-Request': 'from-request',
174
- },
175
- });
176
-
177
- await fetchFn(request);
178
-
179
- expect(dummyFetch).toHaveBeenCalled();
180
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
181
- const headers = calledInit.headers as Record<string, string>;
182
-
183
- expect(calledInit.body).toEqual('{"test": "data"}');
184
- expect(headers['content-type']).toEqual('application/json');
185
- expect(headers['x-from-request']).toEqual('from-request');
186
- expect(headers['x-amz-date']).toEqual('20240315T000000Z');
187
- expect(headers['authorization']).toEqual(
188
- 'AWS4-HMAC-SHA256 Credential=test',
189
- );
190
- expect(headers['user-agent']).toEqual(
191
- 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
192
- );
193
- });
194
-
195
- it('should handle non-string body by stringifying it', async () => {
196
- const dummyResponse = new Response('Signed', { status: 200 });
197
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
198
- const fetchFn = createFetchFunction(dummyFetch);
199
-
200
- const inputUrl = 'http://example.com';
201
- const jsonBody = { field: 'value' };
202
-
203
- await fetchFn(inputUrl, {
204
- method: 'POST',
205
- body: jsonBody as unknown as BodyInit,
206
- headers: {},
207
- });
208
- expect(dummyFetch).toHaveBeenCalled();
209
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
210
- // The body should be stringified.
211
- expect(calledInit.body).toEqual(JSON.stringify(jsonBody));
212
- });
213
-
214
- it('should handle Uint8Array body', async () => {
215
- const dummyResponse = new Response('Signed', { status: 200 });
216
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
217
- const fetchFn = createFetchFunction(dummyFetch);
218
-
219
- const inputUrl = 'http://example.com';
220
- const uint8Body = new TextEncoder().encode('binaryTest');
221
-
222
- await fetchFn(inputUrl, {
223
- method: 'POST',
224
- body: uint8Body,
225
- headers: {},
226
- });
227
- expect(dummyFetch).toHaveBeenCalled();
228
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
229
- // The Uint8Array body should have been decoded to a string.
230
- expect(calledInit.body).toEqual('binaryTest');
231
- });
232
-
233
- it('should handle ArrayBuffer body', async () => {
234
- const dummyResponse = new Response('Signed', { status: 200 });
235
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
236
- const fetchFn = createFetchFunction(dummyFetch);
237
-
238
- const inputUrl = 'http://example.com';
239
- const text = 'bufferTest';
240
- const buffer = new TextEncoder().encode(text).buffer;
241
-
242
- await fetchFn(inputUrl, {
243
- method: 'POST',
244
- body: buffer,
245
- headers: {},
246
- });
247
- expect(dummyFetch).toHaveBeenCalled();
248
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
249
- expect(calledInit.body).toEqual(text);
250
- });
251
-
252
- it('should extract headers from a Headers instance', async () => {
253
- const dummyResponse = new Response('Signed', { status: 200 });
254
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
255
- const fetchFn = createFetchFunction(dummyFetch);
256
-
257
- const h = new Headers();
258
- h.set('A', 'value-a');
259
- h.set('B', 'value-b');
260
-
261
- await fetchFn('http://example.com', {
262
- method: 'POST',
263
- body: '{"test": "data"}',
264
- headers: h,
265
- });
266
- expect(dummyFetch).toHaveBeenCalled();
267
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
268
- const headers = calledInit.headers as Record<string, string>;
269
- expect(headers['a'] || headers['A']).toEqual('value-a');
270
- expect(headers['b'] || headers['B']).toEqual('value-b');
271
- });
272
-
273
- it('should handle headers provided as an array', async () => {
274
- const dummyResponse = new Response('Signed', { status: 200 });
275
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
276
- const fetchFn = createFetchFunction(dummyFetch);
277
-
278
- const headersArray: [string, string][] = [
279
- ['Array-Header', 'array-value'],
280
- ['Another-Header', 'another-value'],
281
- ];
282
-
283
- await fetchFn('http://example.com', {
284
- method: 'POST',
285
- body: '{"test": "data"}',
286
- headers: headersArray,
287
- });
288
- expect(dummyFetch).toHaveBeenCalled();
289
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
290
- const headers = calledInit.headers as Record<string, string>;
291
- expect(headers['array-header'] || headers['Array-Header']).toEqual(
292
- 'array-value',
293
- );
294
- expect(headers['another-header'] || headers['Another-Header']).toEqual(
295
- 'another-value',
296
- );
297
- // Also check that the signing headers are included.
298
- expect(headers['x-amz-date']).toEqual('20240315T000000Z');
299
- expect(headers['authorization']).toEqual(
300
- 'AWS4-HMAC-SHA256 Credential=test',
301
- );
302
- });
303
-
304
- it('should call original fetch if init is undefined', async () => {
305
- const dummyResponse = new Response('OK', { status: 200 });
306
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
307
- const fetchFn = createFetchFunction(dummyFetch);
308
-
309
- const response = await fetchFn('http://example.com');
310
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
311
- headers: {
312
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
313
- },
314
- });
315
- expect(response).toBe(dummyResponse);
316
- });
317
-
318
- it('should correctly handle async credential providers', async () => {
319
- const dummyResponse = new Response('Signed', { status: 200 });
320
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
321
-
322
- // Create a function that returns a Promise of credentials
323
- const asyncCredentialsProvider = () =>
324
- Promise.resolve({
325
- region: 'us-east-1',
326
- accessKeyId: 'async-access-key',
327
- secretAccessKey: 'async-secret-key',
328
- sessionToken: 'async-session-token',
329
- });
330
-
331
- const fetchFn = createSigV4FetchFunction(
332
- asyncCredentialsProvider,
333
- dummyFetch,
334
- );
335
-
336
- await fetchFn('http://example.com', {
337
- method: 'POST',
338
- body: '{"test": "async"}',
339
- headers: {
340
- 'Content-Type': 'application/json',
341
- },
342
- });
343
-
344
- // Verify the request was properly signed
345
- expect(dummyFetch).toHaveBeenCalled();
346
- const calledInit = dummyFetch.mock.calls[0][1] as RequestInit;
347
- const headers = calledInit.headers as Record<string, string>;
348
-
349
- // Check that the signing headers were added
350
- expect(headers['x-amz-date']).toEqual('20240315T000000Z');
351
- expect(headers['authorization']).toEqual(
352
- 'AWS4-HMAC-SHA256 Credential=test',
353
- );
354
- expect(headers['x-amz-security-token']).toEqual('async-session-token');
355
- expect(headers['content-type']).toEqual('application/json');
356
- });
357
-
358
- it('should handle async credential providers that reject', async () => {
359
- const dummyFetch = vi.fn();
360
- const errorMessage = 'Failed to get credentials';
361
-
362
- // Create a function that returns a rejected Promise
363
- const failingCredentialsProvider = () =>
364
- Promise.reject(new Error(errorMessage));
365
-
366
- const fetchFn = createSigV4FetchFunction(
367
- failingCredentialsProvider,
368
- dummyFetch,
369
- );
370
-
371
- // The fetch call should propagate the rejection
372
- await expect(
373
- fetchFn('http://example.com', {
374
- method: 'POST',
375
- body: '{"test": "data"}',
376
- }),
377
- ).rejects.toThrow(errorMessage);
378
-
379
- // The underlying fetch should not be called
380
- expect(dummyFetch).not.toHaveBeenCalled();
381
- });
382
- });
383
-
384
- describe('createApiKeyFetchFunction', () => {
385
- afterEach(() => {
386
- vi.restoreAllMocks();
387
- });
388
-
389
- it('should add Authorization header with Bearer token and user-agent', async () => {
390
- const dummyResponse = new Response('OK', { status: 200 });
391
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
392
- const apiKey = 'test-api-key-123';
393
-
394
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
395
-
396
- const response = await fetchFn('http://example.com', {
397
- method: 'POST',
398
- body: '{"test": "data"}',
399
- headers: {
400
- 'Content-Type': 'application/json',
401
- },
402
- });
403
-
404
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
405
- method: 'POST',
406
- body: '{"test": "data"}',
407
- headers: {
408
- 'content-type': 'application/json',
409
- Authorization: 'Bearer test-api-key-123',
410
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
411
- },
412
- });
413
- expect(response).toBe(dummyResponse);
414
- });
415
-
416
- it('should merge Authorization header with existing headers', async () => {
417
- const dummyResponse = new Response('OK', { status: 200 });
418
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
419
- const apiKey = 'test-api-key-456';
420
-
421
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
422
-
423
- await fetchFn('http://example.com', {
424
- method: 'POST',
425
- body: '{"test": "data"}',
426
- headers: {
427
- 'Content-Type': 'application/json',
428
- 'Custom-Header': 'custom-value',
429
- 'X-Request-ID': 'req-123',
430
- },
431
- });
432
-
433
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
434
- method: 'POST',
435
- body: '{"test": "data"}',
436
- headers: {
437
- 'content-type': 'application/json',
438
- 'custom-header': 'custom-value',
439
- 'x-request-id': 'req-123',
440
- Authorization: 'Bearer test-api-key-456',
441
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
442
- },
443
- });
444
- });
445
-
446
- it('should work with Headers instance', async () => {
447
- const dummyResponse = new Response('OK', { status: 200 });
448
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
449
- const apiKey = 'test-api-key-789';
450
-
451
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
452
-
453
- const headers = new Headers();
454
- headers.set('Content-Type', 'application/json');
455
- headers.set('X-Custom', 'value');
456
-
457
- await fetchFn('http://example.com', {
458
- method: 'POST',
459
- body: '{"test": "data"}',
460
- headers,
461
- });
462
-
463
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
464
- method: 'POST',
465
- body: '{"test": "data"}',
466
- headers: {
467
- 'content-type': 'application/json',
468
- 'x-custom': 'value',
469
- Authorization: 'Bearer test-api-key-789',
470
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
471
- },
472
- });
473
- });
474
-
475
- it('should work with headers as array', async () => {
476
- const dummyResponse = new Response('OK', { status: 200 });
477
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
478
- const apiKey = 'test-api-key-array';
479
-
480
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
481
-
482
- const headersArray: [string, string][] = [
483
- ['Content-Type', 'application/json'],
484
- ['X-Array-Header', 'array-value'],
485
- ];
486
-
487
- await fetchFn('http://example.com', {
488
- method: 'POST',
489
- body: '{"test": "data"}',
490
- headers: headersArray,
491
- });
492
-
493
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
494
- method: 'POST',
495
- body: '{"test": "data"}',
496
- headers: {
497
- 'content-type': 'application/json',
498
- 'x-array-header': 'array-value',
499
- Authorization: 'Bearer test-api-key-array',
500
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
501
- },
502
- });
503
- });
504
-
505
- it('should work with GET requests', async () => {
506
- const dummyResponse = new Response('OK', { status: 200 });
507
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
508
- const apiKey = 'test-api-key-get';
509
-
510
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
511
-
512
- await fetchFn('http://example.com', {
513
- method: 'GET',
514
- headers: {
515
- Accept: 'application/json',
516
- },
517
- });
518
-
519
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
520
- method: 'GET',
521
- headers: {
522
- accept: 'application/json',
523
- Authorization: 'Bearer test-api-key-get',
524
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
525
- },
526
- });
527
- });
528
-
529
- it('should work when no headers are provided', async () => {
530
- const dummyResponse = new Response('OK', { status: 200 });
531
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
532
- const apiKey = 'test-api-key-no-headers';
533
-
534
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
535
-
536
- await fetchFn('http://example.com', {
537
- method: 'POST',
538
- body: '{"test": "data"}',
539
- });
540
-
541
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
542
- method: 'POST',
543
- body: '{"test": "data"}',
544
- headers: {
545
- Authorization: 'Bearer test-api-key-no-headers',
546
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
547
- },
548
- });
549
- });
550
-
551
- it('should work when init is undefined', async () => {
552
- const dummyResponse = new Response('OK', { status: 200 });
553
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
554
- const apiKey = 'test-api-key-undefined';
555
-
556
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
557
-
558
- await fetchFn('http://example.com');
559
-
560
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
561
- headers: {
562
- Authorization: 'Bearer test-api-key-undefined',
563
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
564
- },
565
- });
566
- });
567
-
568
- it('should override existing Authorization header', async () => {
569
- const dummyResponse = new Response('OK', { status: 200 });
570
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
571
- const apiKey = 'test-api-key-override';
572
-
573
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
574
-
575
- await fetchFn('http://example.com', {
576
- method: 'POST',
577
- body: '{"test": "data"}',
578
- headers: {
579
- 'Content-Type': 'application/json',
580
- Authorization: 'Bearer old-token',
581
- },
582
- });
583
-
584
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
585
- method: 'POST',
586
- body: '{"test": "data"}',
587
- headers: {
588
- 'content-type': 'application/json',
589
- Authorization: 'Bearer test-api-key-override',
590
- authorization: 'Bearer old-token',
591
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
592
- },
593
- });
594
- });
595
-
596
- it('should use default fetch when no custom fetch provided', async () => {
597
- const originalFetch = globalThis.fetch;
598
- const mockGlobalFetch = vi.fn().mockResolvedValue(new Response('OK'));
599
- globalThis.fetch = mockGlobalFetch;
600
-
601
- try {
602
- const apiKey = 'test-api-key-default';
603
- const fetchFn = createApiKeyFetchFunction(apiKey);
604
-
605
- await fetchFn('http://example.com', {
606
- method: 'POST',
607
- body: '{"test": "data"}',
608
- });
609
-
610
- expect(mockGlobalFetch).toHaveBeenCalledWith('http://example.com', {
611
- method: 'POST',
612
- body: '{"test": "data"}',
613
- headers: {
614
- Authorization: 'Bearer test-api-key-default',
615
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
616
- },
617
- });
618
- } finally {
619
- globalThis.fetch = originalFetch;
620
- }
621
- });
622
-
623
- it('should handle empty string API key', async () => {
624
- const dummyResponse = new Response('OK', { status: 200 });
625
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
626
- const apiKey = '';
627
-
628
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
629
-
630
- await fetchFn('http://example.com', {
631
- method: 'POST',
632
- body: '{"test": "data"}',
633
- });
634
-
635
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
636
- method: 'POST',
637
- body: '{"test": "data"}',
638
- headers: {
639
- Authorization: 'Bearer ',
640
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
641
- },
642
- });
643
- });
644
-
645
- it('should preserve request body and other properties', async () => {
646
- const dummyResponse = new Response('OK', { status: 200 });
647
- const dummyFetch = vi.fn().mockResolvedValue(dummyResponse);
648
- const apiKey = 'test-api-key-preserve';
649
-
650
- const fetchFn = createApiKeyFetchFunction(apiKey, dummyFetch);
651
-
652
- const requestBody = JSON.stringify({ data: 'test' });
653
- await fetchFn('http://example.com', {
654
- method: 'PUT',
655
- body: requestBody,
656
- headers: {
657
- 'Content-Type': 'application/json',
658
- },
659
- credentials: 'include',
660
- cache: 'no-cache',
661
- });
662
-
663
- expect(dummyFetch).toHaveBeenCalledWith('http://example.com', {
664
- method: 'PUT',
665
- body: requestBody,
666
- headers: {
667
- 'content-type': 'application/json',
668
- Authorization: 'Bearer test-api-key-preserve',
669
- 'user-agent': 'ai-sdk/amazon-bedrock/0.0.0-test runtime/testenv',
670
- },
671
- credentials: 'include',
672
- cache: 'no-cache',
673
- });
674
- });
675
- });