@anthropic-ai/bedrock-sdk
Version:
The official TypeScript library for the Anthropic Bedrock API
100 lines (89 loc) • 3.12 kB
text/typescript
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
type HeaderValue = string | undefined | null;
export type HeadersLike =
| Headers
| readonly HeaderValue[][]
| Record<string, HeaderValue | readonly HeaderValue[]>
| undefined
| null
| NullableHeaders;
const brand_privateNullableHeaders = Symbol.for('brand.privateNullableHeaders') as symbol & {
description: 'brand.privateNullableHeaders';
};
/**
* @internal
* Users can pass explicit nulls to unset default headers. When we parse them
* into a standard headers type we need to preserve that information.
*/
export type NullableHeaders = {
/** Brand check, prevent users from creating a NullableHeaders. */
[_: typeof brand_privateNullableHeaders]: true;
/** Parsed headers. */
values: Headers;
/** Set of lowercase header names explicitly set to null. */
nulls: Set<string>;
};
const isArray = Array.isArray as (val: unknown) => val is readonly unknown[];
function* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {
if (!headers) return;
if (brand_privateNullableHeaders in headers) {
const { values, nulls } = headers as NullableHeaders;
yield* values.entries();
for (const name of nulls) {
yield [name, null];
}
return;
}
let shouldClear = false;
let iter: Iterable<readonly (HeaderValue | readonly HeaderValue[])[]>;
if (headers instanceof Headers) {
iter = headers.entries();
} else if (isArray(headers)) {
iter = headers;
} else {
shouldClear = true;
iter = Object.entries(headers ?? {});
}
for (let row of iter) {
const name = row[0];
if (typeof name !== 'string') throw new TypeError('expected header name to be a string');
const values = isArray(row[1]) ? row[1] : [row[1]];
let didClear = false;
for (const value of values) {
if (value === undefined) continue;
// Objects keys always overwrite older headers, they never append.
// Yield a null to clear the header before adding the new values.
if (shouldClear && !didClear) {
didClear = true;
yield [name, null];
}
yield [name, value];
}
}
}
export const buildHeaders = (newHeaders: HeadersLike[]): NullableHeaders => {
const targetHeaders = new Headers();
const nullHeaders = new Set<string>();
for (const headers of newHeaders) {
const seenHeaders = new Set<string>();
for (const [name, value] of iterateHeaders(headers)) {
const lowerName = name.toLowerCase();
if (!seenHeaders.has(lowerName)) {
targetHeaders.delete(name);
seenHeaders.add(lowerName);
}
if (value === null) {
targetHeaders.delete(name);
nullHeaders.add(lowerName);
} else {
targetHeaders.append(name, value);
nullHeaders.delete(lowerName);
}
}
}
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
};
export const isEmptyHeaders = (headers: HeadersLike) => {
for (const _ of iterateHeaders(headers)) return false;
return true;
};