summaryrefslogtreecommitdiffhomepage
path: root/packages/sdk/src/internal/headers.ts
diff options
context:
space:
mode:
authoradamdotdevin <[email protected]>2025-07-22 11:50:51 -0500
committeradamdotdevin <[email protected]>2025-07-22 11:50:51 -0500
commit10c8b495907069461f5dc464f6285321290c8b14 (patch)
tree9fed07910dd7d99688c0261a364d810a500e21d3 /packages/sdk/src/internal/headers.ts
parent500cea5ce7fa635a924cd9abea63aaf672f7645d (diff)
downloadopencode-10c8b495907069461f5dc464f6285321290c8b14.tar.gz
opencode-10c8b495907069461f5dc464f6285321290c8b14.zip
chore: generate sdk into packages/sdk
Diffstat (limited to 'packages/sdk/src/internal/headers.ts')
-rw-r--r--packages/sdk/src/internal/headers.ts97
1 files changed, 97 insertions, 0 deletions
diff --git a/packages/sdk/src/internal/headers.ts b/packages/sdk/src/internal/headers.ts
new file mode 100644
index 000000000..c724a9d22
--- /dev/null
+++ b/packages/sdk/src/internal/headers.ts
@@ -0,0 +1,97 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { isReadonlyArray } from './utils/values';
+
+type HeaderValue = string | undefined | null;
+export type HeadersLike =
+ | Headers
+ | readonly HeaderValue[][]
+ | Record<string, HeaderValue | readonly HeaderValue[]>
+ | undefined
+ | null
+ | NullableHeaders;
+
+const brand_privateNullableHeaders = /* @__PURE__ */ Symbol('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. */
+ [brand_privateNullableHeaders]: true;
+ /** Parsed headers. */
+ values: Headers;
+ /** Set of lowercase header names explicitly set to null. */
+ nulls: Set<string>;
+};
+
+function* iterateHeaders(headers: HeadersLike): IterableIterator<readonly [string, string | null]> {
+ if (!headers) return;
+
+ if (brand_privateNullableHeaders in headers) {
+ const { values, nulls } = headers;
+ 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 (isReadonlyArray(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 = isReadonlyArray(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;
+};