//#region src/client/stream/transport/utils.ts
const isRecord = (value) => typeof value === "object" && value !== null;
/**
* Resolve a {@link ProtocolPath} against the transport's currently-bound
* thread.
*
* - a fixed `string` is used verbatim (back-compat: a baked path is
*   independent of the bound thread);
* - a function path and the default fallback are evaluated against
*   `threadId`, so late-bound / re-bound adapters target the right thread.
*
* Throws when neither a fixed path nor a bound thread is available — i.e.
* a request was attempted before `client.threads.stream(threadId, …)` /
* {@link TransportAdapter.setThreadId} bound a thread.
*/
function resolveProtocolPath(path, threadId, fallback) {
	if (typeof path === "string") return path;
	if (!threadId) throw new Error("Protocol transport has no bound threadId. Bind one — the framework calls client.threads.stream(threadId, { transport }) / transport.setThreadId(threadId) — before issuing requests.");
	return path ? path(threadId) : fallback(threadId);
}
/** Match {@link BaseClient.prepareFetchOptions}: preserve any apiUrl path prefix. */
const toAbsoluteUrl = (apiUrl, path) => new URL(`${apiUrl.replace(/\/$/, "")}${path}`);
const toError = (error) => error instanceof Error ? error : new Error(String(error));
const toWebSocketUrl = (apiUrl) => {
	const url = new URL(apiUrl);
	url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
	url.search = "";
	url.hash = "";
	return url.toString();
};
const hasHeaders = (headers) => Object.values(headers ?? {}).some((value) => value != null);
function mergeHeaders(...headerGroups) {
	const merged = new Headers();
	for (const group of headerGroups) {
		if (!group) continue;
		if (group instanceof Headers) {
			group.forEach((value, key) => {
				merged.set(key, value);
			});
			continue;
		}
		if (Array.isArray(group)) {
			for (const [key, value] of group) if (value == null) merged.delete(key);
			else merged.set(key, value);
			continue;
		}
		for (const [key, value] of Object.entries(group)) if (value == null) merged.delete(key);
		else merged.set(key, value);
	}
	return merged;
}
function isProtocolResponse(value) {
	return isRecord(value) && typeof value.type === "string" && (value.type === "success" || value.type === "error");
}
//#endregion
export { hasHeaders, isProtocolResponse, isRecord, mergeHeaders, resolveProtocolPath, toAbsoluteUrl, toError, toWebSocketUrl };

//# sourceMappingURL=utils.js.map