🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@aptos-labs/aptos-client

Package Overview
Dependencies
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aptos-labs/aptos-client - npm Package Compare versions

Comparing version
3.0.2
to
4.0.0
+55
dist/cookieJar.d.ts
/** A parsed cookie with optional attributes. */
export interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
export declare class CookieJar {
private jar;
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(jar?: Map<string, Cookie[]>);
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string): void;
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[];
/** Remove all stored cookies. Useful for test isolation. */
clear(): void;
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie;
}
//# sourceMappingURL=cookieJar.d.ts.map
{"version":3,"file":"cookieJar.d.ts","sourceRoot":"","sources":["../src/cookieJar.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,SAAS;IAKR,OAAO,CAAC,GAAG;IAJvB,MAAM,CAAC,QAAQ,CAAC,sBAAsB,MAAM;IAC5C,+DAA+D;IAC/D,MAAM,CAAC,QAAQ,CAAC,eAAe,QAAQ;gBAEnB,GAAG,wBAA8B;IAErD;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM;IA8BrC;;;;;OAKG;IACH,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,EAAE;IA0B9B,4DAA4D;IAC5D,KAAK;IAIL;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;CAsElC"}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
export class CookieJar {
jar;
static MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static MAX_COOKIE_SIZE = 8192;
constructor(jar = new Map()) {
this.jar = jar;
}
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url, cookieStr) {
if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {
return; // Silently drop oversized cookies
}
let cookie;
try {
cookie = CookieJar.parse(cookieStr);
}
catch {
return; // Silently skip malformed cookies, matching browser behavior
}
// RFC 6265bis: SameSite=None requires the Secure attribute
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
// Evict oldest cookies if we're at the per-origin cap
while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url) {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now)
return false;
return true;
});
// Write back to evict expired cookies from storage
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
}
else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str) {
const parts = str.split(";").map((part) => part.trim());
let cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
// RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
// Reject control characters in value that could enable header injection
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value,
};
}
else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
// Only strip quotes when both opening and closing characters match
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax")
cookie.sameSite = "Lax";
else if (normalized === "none")
cookie.sameSite = "None";
else if (normalized === "strict")
cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
}
/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */
const TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name) {
return TOKEN_RE.test(name);
}
/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */
function hasControlChars(str) {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 0x1f || code === 0x7f)
return true;
}
return false;
}
//# sourceMappingURL=cookieJar.js.map
{"version":3,"file":"cookieJar.js","sourceRoot":"","sources":["../src/cookieJar.ts"],"names":[],"mappings":"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"}
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*/
export default function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
//# sourceMappingURL=index.browser.d.ts.map
{"version":3,"file":"index.browser.d.ts","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIzF;;;;;;;;GAQG;AACH,wBAA8B,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAE7G;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAarG;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAavG"}
/**
* Browser HTTP client using the native `fetch()` API.
*
* @remarks
* Selected via the `"browser"` export condition. HTTP/2 negotiation is
* handled by the browser engine — the {@link AptosClientRequest.http2 | http2}
* option is ignored. Cookie handling is delegated to the browser; this entry
* point does not use a {@link CookieJar}.
*
* The `credentials` mode on each request is controlled via
* `overrides.WITH_CREDENTIALS` (`false` → `"omit"`,
* default/`true` → `"include"`).
*
* @module index.browser
*/
import { applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody } from "./shared.js";
let http2Warned = false;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*/
export default async function aptosClient(options) {
return jsonRequest(options);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export async function jsonRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export async function bcsRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/** Build the URL and `RequestInit` from the caller's options. @internal */
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== undefined) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== undefined) {
headers.set(key, String(value));
}
}
const body = serializeBody(options.body);
if (body !== undefined) {
applyJsonContentType(options.body, headers);
}
const credentials = options.overrides?.WITH_CREDENTIALS === false ? "omit" : "include";
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body,
credentials,
};
const requestUrl = buildUrl(options.url, options.params);
return { requestUrl: requestUrl.toString(), requestConfig };
}
//# sourceMappingURL=index.browser.js.map
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":"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"}
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { Cookie } from "./cookieJar.js";
export { CookieJar } from "./cookieJar.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
//# sourceMappingURL=index.fetch.d.ts.map
{"version":3,"file":"index.fetch.d.ts","sourceRoot":"","sources":["../src/index.fetch.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAE1E,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAMzF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAA8B,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAE7G;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAcrG;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAcvG"}
/**
* Fetch-based HTTP client for runtimes with native HTTP/2 support.
*
* @remarks
* Used by Deno, Bun, React Native, and any other runtime that provides a
* spec-compliant `fetch()`. These runtimes negotiate HTTP/2 automatically
* via ALPN, so the {@link AptosClientRequest.http2 | http2} option is
* ignored.
*
* @module index.fetch
*/
import { CookieJar } from "./cookieJar.js";
import { applyCookiesToHeaders, applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody, storeResponseCookies, } from "./shared.js";
export { CookieJar } from "./cookieJar.js";
const defaultCookieJar = new CookieJar();
let http2Warned = false;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default async function aptosClient(options) {
return jsonRequest(options);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export async function jsonRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export async function bcsRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/** Build the URL and `RequestInit` from the caller's options. @internal */
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== undefined) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const jar = options.cookieJar ?? defaultCookieJar;
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== undefined) {
headers.set(key, String(value));
}
}
const requestUrl = buildUrl(options.url, options.params);
applyCookiesToHeaders(headers, requestUrl, jar);
const body = serializeBody(options.body);
if (body !== undefined) {
applyJsonContentType(options.body, headers);
}
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body,
};
return { requestUrl: requestUrl.toString(), requestConfig, jar };
}
//# sourceMappingURL=index.fetch.js.map
{"version":3,"file":"index.fetch.js","sourceRoot":"","sources":["../src/index.fetch.ts"],"names":[],"mappings":"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"}
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { Cookie } from "./cookieJar.js";
export { CookieJar } from "./cookieJar.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
*/
export declare function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param requestOptions - Request configuration.
*/
export declare function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
//# sourceMappingURL=index.node.d.ts.map
{"version":3,"file":"index.node.d.ts","sourceRoot":"","sources":["../src/index.node.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAiB,MAAM,YAAY,CAAC;AAEzF,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQzF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAA8B,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAEpH;AAED;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAE5G;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,cAAc,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,CAE9G"}
/**
* Node.js HTTP client backed by {@link https://undici.nodejs.org | undici}.
*
* @remarks
* This entry point is selected when the package is imported from Node.js
* (via the `"node"` export condition). It uses undici's `Agent` with
* configurable HTTP/2 support (`allowH2`). Agents are cached per origin
* so connections are reused across requests to the same host.
*
* @module index.node
*/
import { Agent } from "undici";
import { CookieJar } from "./cookieJar.js";
import { applyCookiesToHeaders, applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody, storeResponseCookies, } from "./shared.js";
export { CookieJar } from "./cookieJar.js";
const defaultCookieJar = new CookieJar();
/** One dispatcher per origin + HTTP/2 mode for connection reuse. */
const dispatcherCache = new Map();
const MAX_DISPATCHERS = 50;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default async function aptosClient(requestOptions) {
return jsonRequest(requestOptions);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
*/
export async function jsonRequest(requestOptions) {
return await doRequest(requestOptions, "json");
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param requestOptions - Request configuration.
*/
export async function bcsRequest(requestOptions) {
return await doRequest(requestOptions, "arrayBuffer");
}
/**
* Core request handler shared by {@link jsonRequest} and {@link bcsRequest}.
* @internal
*/
async function doRequest(requestOptions, mode) {
const { url, method, params, headers, body, http2 = true } = requestOptions;
const jar = requestOptions.cookieJar ?? defaultCookieJar;
if (method !== "GET" && method !== "POST") {
throw new Error(`Unsupported method: ${method}`);
}
const requestUrl = buildUrl(url, params);
const requestHeaders = buildHeaders(requestUrl, headers, jar);
const dispatcher = getDispatcher(requestUrl.origin, http2);
const init = {
method,
headers: requestHeaders,
dispatcher,
};
const serialized = serializeBody(body);
if (serialized !== undefined) {
init.body = serialized;
applyJsonContentType(body, requestHeaders);
}
const res = await fetch(requestUrl, init);
storeResponseCookies(requestUrl, res.headers, jar);
const data = mode === "json" ? await parseJsonSafely(res) : await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
config: { ...init, headers: headersToRecord(requestHeaders) },
request: {
url: requestUrl.toString(),
method,
},
response: res,
headers: headersToRecord(res.headers),
};
}
/**
* Return a cached undici `Agent` for the given origin, creating one if needed.
*
* @param origin - URL origin (scheme + host + port).
* @param http2 - Whether to enable HTTP/2 via ALPN (`allowH2`).
* @internal
*/
function getDispatcher(origin, http2) {
const key = `${origin}|h2=${http2}`;
const cached = dispatcherCache.get(key);
if (cached) {
// Move to end of Map (most-recently-used)
dispatcherCache.delete(key);
dispatcherCache.set(key, cached);
return cached;
}
// Evict oldest entry if cache is full
if (dispatcherCache.size >= MAX_DISPATCHERS) {
// biome-ignore lint/style/noNonNullAssertion: cache size check guarantees entry exists
const oldest = dispatcherCache.keys().next().value;
// biome-ignore lint/style/noNonNullAssertion: oldest key was just retrieved from cache
dispatcherCache
.get(oldest)
.destroy()
.catch(() => { });
dispatcherCache.delete(oldest);
}
const agent = new Agent({
allowH2: http2,
});
dispatcherCache.set(key, agent);
return agent;
}
/**
* Merge caller-supplied headers with cookies from the jar.
* @internal
*/
function buildHeaders(url, headers, jar) {
const result = new Headers();
for (const [key, value] of Object.entries(headers ?? {})) {
if (value !== undefined) {
result.set(key, String(value));
}
}
applyCookiesToHeaders(result, url, jar);
return result;
}
//# sourceMappingURL=index.node.js.map
{"version":3,"file":"index.node.js","sourceRoot":"","sources":["../src/index.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,QAAQ,EACR,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,MAAM,gBAAgB,GAAG,IAAI,SAAS,EAAE,CAAC;AAEzC,oEAAoE;AACpE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAiB,CAAC;AACjD,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,WAAW,CAAM,cAAkC;IAC/E,OAAO,WAAW,CAAC,cAAc,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAM,cAAkC;IACvE,OAAO,MAAM,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,cAAkC;IACjE,OAAO,MAAM,SAAS,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;AACxD,CAAC;AAKD;;;GAGG;AACH,KAAK,UAAU,SAAS,CACtB,cAAkC,EAClC,IAAkB;IAElB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,cAAc,CAAC;IAC5E,MAAM,GAAG,GAAG,cAAc,CAAC,SAAS,IAAI,gBAAgB,CAAC;IAEzD,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,uBAAuB,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE3D,MAAM,IAAI,GAAyC;QACjD,MAAM;QACN,OAAO,EAAE,cAAc;QACvB,UAAU;KACX,CAAC;IAEF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,oBAAoB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAE1C,oBAAoB,CAAC,UAAU,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAG,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;IAEpF,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,IAAI;QACJ,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,eAAe,CAAC,cAAc,CAAC,EAAE;QAC7D,OAAO,EAAE;YACP,GAAG,EAAE,UAAU,CAAC,QAAQ,EAAE;YAC1B,MAAM;SACP;QACD,QAAQ,EAAE,GAAG;QACb,OAAO,EAAE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC;KACtC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,MAAc,EAAE,KAAc;IACnD,MAAM,GAAG,GAAG,GAAG,MAAM,OAAO,KAAK,EAAE,CAAC;IACpC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,MAAM,EAAE,CAAC;QACX,0CAA0C;QAC1C,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC5B,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,sCAAsC;IACtC,IAAI,eAAe,CAAC,IAAI,IAAI,eAAe,EAAE,CAAC;QAC5C,uFAAuF;QACvF,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC;QACpD,uFAAuF;QACvF,eAAe;aACZ,GAAG,CAAC,MAAM,CAAE;aACZ,OAAO,EAAE;aACT,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnB,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACtB,OAAO,EAAE,KAAK;KACf,CAAC,CAAC;IAEH,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,SAAS,YAAY,CAAC,GAAQ,EAAE,OAAkD,EAAE,GAAkB;IACpG,MAAM,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;IAE7B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAExC,OAAO,MAAM,CAAC;AAChB,CAAC"}
/**
* Shared utilities used by all entry points (Node, fetch, browser).
*
* @remarks
* Extracted to a single module so that parsing, serialization, URL building,
* and cookie logic stay consistent across runtimes.
*
* @internal
* @module shared
*/
import type { AptosClientRequest, CookieJarLike } from "./types.js";
/**
* Build a `URL` from a base string and optional query parameters.
* `bigint` values are stringified automatically via `String()`.
* @internal
*/
export declare function buildUrl(base: string, params?: AptosClientRequest["params"]): URL;
/**
* Serialize a request body to a `BodyInit`-compatible value.
*
* - `null` / `undefined` → `undefined` (no body sent)
* - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)
* - Anything else → `JSON.stringify`
*
* @internal
*/
export declare function serializeBody(body: unknown): BodyInit | undefined;
/**
* Set the `content-type` header to `application/json` when the body is
* a non-binary, non-null value and no content-type has been set already.
* @internal
*/
export declare function applyJsonContentType(body: unknown, headers: Headers): void;
/**
* Parse a response body as JSON, returning the raw text when parsing fails.
*
* Returning raw text (instead of throwing) preserves backward compatibility
* with v2, where `got` returned error responses as normal `AptosClientResponse`
* objects. This lets the caller (e.g. the TS SDK) inspect the status code and
* handle the error however it chooses.
*
* @internal
*/
export declare function parseJsonSafely(res: Response): Promise<any>;
/**
* Merge cookies from a {@link CookieJarLike} into the request headers.
* @internal
*/
export declare function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void;
/**
* Store any `Set-Cookie` headers from the response in the cookie jar.
*
* Includes a defensive check for `Headers.getSetCookie()` availability,
* since it may be absent in some React Native environments.
* @internal
*/
export declare function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void;
/**
* Convert a `Headers` instance to a plain `Record<string, string | string[]>`.
*
* This preserves backward compatibility with aptos-client v2, which
* returned Node's `IncomingHttpHeaders` (a plain object) from the `got`
* library. Consumers (e.g. the TS SDK) access headers via bracket
* notation (`response.headers["x-aptos-cursor"]`), which only works on
* plain objects — not on `Headers` instances.
*
* Multi-value `set-cookie` headers are returned as `string[]` to match
* Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.
*
* @internal
*/
export declare function headersToRecord(headers: Headers): Record<string, string | string[]>;
//# sourceMappingURL=shared.d.ts.map
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,GAAG,GAAG,CAWjF;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAI1E;AAED;;;;;;;;;GASG;AAEH,wBAAsB,eAAe,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAajE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAO1F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAKzF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAYnF"}
/**
* Build a `URL` from a base string and optional query parameters.
* `bigint` values are stringified automatically via `String()`.
* @internal
*/
export function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== undefined) {
// String(value) correctly handles bigint: String(12345n) === "12345"
url.searchParams.append(key, String(value));
}
}
}
return url;
}
/**
* Serialize a request body to a `BodyInit`-compatible value.
*
* - `null` / `undefined` → `undefined` (no body sent)
* - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)
* - Anything else → `JSON.stringify`
*
* @internal
*/
export function serializeBody(body) {
if (body == null)
return undefined;
if (body instanceof Uint8Array) {
// Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility
return body;
}
return JSON.stringify(body);
}
/**
* Set the `content-type` header to `application/json` when the body is
* a non-binary, non-null value and no content-type has been set already.
* @internal
*/
export function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
/**
* Parse a response body as JSON, returning the raw text when parsing fails.
*
* Returning raw text (instead of throwing) preserves backward compatibility
* with v2, where `got` returned error responses as normal `AptosClientResponse`
* objects. This lets the caller (e.g. the TS SDK) inspect the status code and
* handle the error however it chooses.
*
* @internal
*/
// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic
export async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
}
catch {
return text;
}
}
/**
* Merge cookies from a {@link CookieJarLike} into the request headers.
* @internal
*/
export function applyCookiesToHeaders(headers, url, jar) {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
/**
* Store any `Set-Cookie` headers from the response in the cookie jar.
*
* Includes a defensive check for `Headers.getSetCookie()` availability,
* since it may be absent in some React Native environments.
* @internal
*/
export function storeResponseCookies(url, headers, jar) {
if (typeof headers.getSetCookie !== "function")
return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
/**
* Convert a `Headers` instance to a plain `Record<string, string | string[]>`.
*
* This preserves backward compatibility with aptos-client v2, which
* returned Node's `IncomingHttpHeaders` (a plain object) from the `got`
* library. Consumers (e.g. the TS SDK) access headers via bracket
* notation (`response.headers["x-aptos-cursor"]`), which only works on
* plain objects — not on `Headers` instances.
*
* Multi-value `set-cookie` headers are returned as `string[]` to match
* Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.
*
* @internal
*/
export function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
//# sourceMappingURL=shared.js.map
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"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"}
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
export type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
export interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
export type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
//# sourceMappingURL=types.d.ts.map
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,CAAC,GAAG,IAAI;IACrC,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,IAAI,EAAE,GAAG,CAAC;IACV,8DAA8D;IAE9D,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,mEAAmE;IAEnE,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,yDAAyD;IAEzD,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CAC7C,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACxD,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kGAAkG;IAClG,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;IACxE,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC3C;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B,CAAC"}
export {};
//# sourceMappingURL=types.js.map
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
/** A parsed cookie with optional attributes. */
export interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
export class CookieJar {
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(private jar = new Map<string, Cookie[]>()) {}
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string) {
if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {
return; // Silently drop oversized cookies
}
let cookie: Cookie;
try {
cookie = CookieJar.parse(cookieStr);
} catch {
return; // Silently skip malformed cookies, matching browser behavior
}
// RFC 6265bis: SameSite=None requires the Secure attribute
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
// Evict oldest cookies if we're at the per-origin cap
while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[] {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now) return false;
return true;
});
// Write back to evict expired cookies from storage
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
} else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie {
const parts = str.split(";").map((part) => part.trim());
let cookie: Cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
// RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
// Reject control characters in value that could enable header injection
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value,
};
} else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
// Only strip quotes when both opening and closing characters match
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax") cookie.sameSite = "Lax";
else if (normalized === "none") cookie.sameSite = "None";
else if (normalized === "strict") cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
}
/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */
const TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name: string): boolean {
return TOKEN_RE.test(name);
}
/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */
function hasControlChars(str: string): boolean {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 0x1f || code === 0x7f) return true;
}
return false;
}
/**
* Browser HTTP client using the native `fetch()` API.
*
* @remarks
* Selected via the `"browser"` export condition. HTTP/2 negotiation is
* handled by the browser engine — the {@link AptosClientRequest.http2 | http2}
* option is ignored. Cookie handling is delegated to the browser; this entry
* point does not use a {@link CookieJar}.
*
* The `credentials` mode on each request is controlled via
* `overrides.WITH_CREDENTIALS` (`false` → `"omit"`,
* default/`true` → `"include"`).
*
* @module index.browser
*/
import { applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody } from "./shared.js";
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
let http2Warned = false;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*/
export default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
return jsonRequest<Res>(options);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/** Build the URL and `RequestInit` from the caller's options. @internal */
function buildRequest(options: AptosClientRequest) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== undefined) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== undefined) {
headers.set(key, String(value));
}
}
const body = serializeBody(options.body);
if (body !== undefined) {
applyJsonContentType(options.body, headers);
}
const credentials: RequestCredentials = options.overrides?.WITH_CREDENTIALS === false ? "omit" : "include";
const requestConfig: RequestInit = {
method: options.method,
headers: headersToRecord(headers) as Record<string, string>,
body,
credentials,
};
const requestUrl = buildUrl(options.url, options.params);
return { requestUrl: requestUrl.toString(), requestConfig };
}
/**
* Fetch-based HTTP client for runtimes with native HTTP/2 support.
*
* @remarks
* Used by Deno, Bun, React Native, and any other runtime that provides a
* spec-compliant `fetch()`. These runtimes negotiate HTTP/2 automatically
* via ALPN, so the {@link AptosClientRequest.http2 | http2} option is
* ignored.
*
* @module index.fetch
*/
import { CookieJar } from "./cookieJar.js";
import {
applyCookiesToHeaders,
applyJsonContentType,
buildUrl,
headersToRecord,
parseJsonSafely,
serializeBody,
storeResponseCookies,
} from "./shared.js";
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { Cookie } from "./cookieJar.js";
export { CookieJar } from "./cookieJar.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
const defaultCookieJar = new CookieJar();
let http2Warned = false;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
return jsonRequest<Res>(options);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/** Build the URL and `RequestInit` from the caller's options. @internal */
function buildRequest(options: AptosClientRequest) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== undefined) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const jar = options.cookieJar ?? defaultCookieJar;
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== undefined) {
headers.set(key, String(value));
}
}
const requestUrl = buildUrl(options.url, options.params);
applyCookiesToHeaders(headers, requestUrl, jar);
const body = serializeBody(options.body);
if (body !== undefined) {
applyJsonContentType(options.body, headers);
}
const requestConfig: RequestInit = {
method: options.method,
headers: headersToRecord(headers) as Record<string, string>,
body,
};
return { requestUrl: requestUrl.toString(), requestConfig, jar };
}
/**
* Node.js HTTP client backed by {@link https://undici.nodejs.org | undici}.
*
* @remarks
* This entry point is selected when the package is imported from Node.js
* (via the `"node"` export condition). It uses undici's `Agent` with
* configurable HTTP/2 support (`allowH2`). Agents are cached per origin
* so connections are reused across requests to the same host.
*
* @module index.node
*/
import { Agent } from "undici";
import { CookieJar } from "./cookieJar.js";
import {
applyCookiesToHeaders,
applyJsonContentType,
buildUrl,
headersToRecord,
parseJsonSafely,
serializeBody,
storeResponseCookies,
} from "./shared.js";
import type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
export type { Cookie } from "./cookieJar.js";
export { CookieJar } from "./cookieJar.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
const defaultCookieJar = new CookieJar();
/** One dispatcher per origin + HTTP/2 mode for connection reuse. */
const dispatcherCache = new Map<string, Agent>();
const MAX_DISPATCHERS = 50;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default async function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {
return jsonRequest(requestOptions);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
*/
export async function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {
return await doRequest(requestOptions, "json");
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param requestOptions - Request configuration.
*/
export async function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {
return await doRequest(requestOptions, "arrayBuffer");
}
/** @internal */
type ResponseMode = "json" | "arrayBuffer";
/**
* Core request handler shared by {@link jsonRequest} and {@link bcsRequest}.
* @internal
*/
async function doRequest<Res>(
requestOptions: AptosClientRequest,
mode: ResponseMode,
): Promise<AptosClientResponse<Res>> {
const { url, method, params, headers, body, http2 = true } = requestOptions;
const jar = requestOptions.cookieJar ?? defaultCookieJar;
if (method !== "GET" && method !== "POST") {
throw new Error(`Unsupported method: ${method}`);
}
const requestUrl = buildUrl(url, params);
const requestHeaders = buildHeaders(requestUrl, headers, jar);
const dispatcher = getDispatcher(requestUrl.origin, http2);
const init: RequestInit & { dispatcher?: Agent } = {
method,
headers: requestHeaders,
dispatcher,
};
const serialized = serializeBody(body);
if (serialized !== undefined) {
init.body = serialized;
applyJsonContentType(body, requestHeaders);
}
const res = await fetch(requestUrl, init);
storeResponseCookies(requestUrl, res.headers, jar);
const data = mode === "json" ? await parseJsonSafely(res) : await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
config: { ...init, headers: headersToRecord(requestHeaders) },
request: {
url: requestUrl.toString(),
method,
},
response: res,
headers: headersToRecord(res.headers),
};
}
/**
* Return a cached undici `Agent` for the given origin, creating one if needed.
*
* @param origin - URL origin (scheme + host + port).
* @param http2 - Whether to enable HTTP/2 via ALPN (`allowH2`).
* @internal
*/
function getDispatcher(origin: string, http2: boolean): Agent {
const key = `${origin}|h2=${http2}`;
const cached = dispatcherCache.get(key);
if (cached) {
// Move to end of Map (most-recently-used)
dispatcherCache.delete(key);
dispatcherCache.set(key, cached);
return cached;
}
// Evict oldest entry if cache is full
if (dispatcherCache.size >= MAX_DISPATCHERS) {
// biome-ignore lint/style/noNonNullAssertion: cache size check guarantees entry exists
const oldest = dispatcherCache.keys().next().value!;
// biome-ignore lint/style/noNonNullAssertion: oldest key was just retrieved from cache
dispatcherCache
.get(oldest)!
.destroy()
.catch(() => {});
dispatcherCache.delete(oldest);
}
const agent = new Agent({
allowH2: http2,
});
dispatcherCache.set(key, agent);
return agent;
}
/**
* Merge caller-supplied headers with cookies from the jar.
* @internal
*/
function buildHeaders(url: URL, headers: AptosClientRequest["headers"] | undefined, jar: CookieJarLike): Headers {
const result = new Headers();
for (const [key, value] of Object.entries(headers ?? {})) {
if (value !== undefined) {
result.set(key, String(value));
}
}
applyCookiesToHeaders(result, url, jar);
return result;
}
/**
* Shared utilities used by all entry points (Node, fetch, browser).
*
* @remarks
* Extracted to a single module so that parsing, serialization, URL building,
* and cookie logic stay consistent across runtimes.
*
* @internal
* @module shared
*/
import type { AptosClientRequest, CookieJarLike } from "./types.js";
/**
* Build a `URL` from a base string and optional query parameters.
* `bigint` values are stringified automatically via `String()`.
* @internal
*/
export function buildUrl(base: string, params?: AptosClientRequest["params"]): URL {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== undefined) {
// String(value) correctly handles bigint: String(12345n) === "12345"
url.searchParams.append(key, String(value));
}
}
}
return url;
}
/**
* Serialize a request body to a `BodyInit`-compatible value.
*
* - `null` / `undefined` → `undefined` (no body sent)
* - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)
* - Anything else → `JSON.stringify`
*
* @internal
*/
export function serializeBody(body: unknown): BodyInit | undefined {
if (body == null) return undefined;
if (body instanceof Uint8Array) {
// Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility
return body as unknown as BodyInit;
}
return JSON.stringify(body);
}
/**
* Set the `content-type` header to `application/json` when the body is
* a non-binary, non-null value and no content-type has been set already.
* @internal
*/
export function applyJsonContentType(body: unknown, headers: Headers): void {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
/**
* Parse a response body as JSON, returning the raw text when parsing fails.
*
* Returning raw text (instead of throwing) preserves backward compatibility
* with v2, where `got` returned error responses as normal `AptosClientResponse`
* objects. This lets the caller (e.g. the TS SDK) inspect the status code and
* handle the error however it chooses.
*
* @internal
*/
// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic
export async function parseJsonSafely(res: Response): Promise<any> {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
/**
* Merge cookies from a {@link CookieJarLike} into the request headers.
* @internal
*/
export function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
/**
* Store any `Set-Cookie` headers from the response in the cookie jar.
*
* Includes a defensive check for `Headers.getSetCookie()` availability,
* since it may be absent in some React Native environments.
* @internal
*/
export function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {
if (typeof headers.getSetCookie !== "function") return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
/**
* Convert a `Headers` instance to a plain `Record<string, string | string[]>`.
*
* This preserves backward compatibility with aptos-client v2, which
* returned Node's `IncomingHttpHeaders` (a plain object) from the `got`
* library. Consumers (e.g. the TS SDK) access headers via bracket
* notation (`response.headers["x-aptos-cursor"]`), which only works on
* plain objects — not on `Headers` instances.
*
* Multi-value `set-cookie` headers are returned as `string[]` to match
* Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.
*
* @internal
*/
export function headersToRecord(headers: Headers): Record<string, string | string[]> {
const result: Record<string, string | string[]> = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
export type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
// biome-ignore lint/suspicious/noExplicitAny: cross-platform response type; varies per entry point
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
// biome-ignore lint/suspicious/noExplicitAny: cross-platform response type; varies per entry point
request?: any;
/** The raw `Response` object (Node entry point only). */
// biome-ignore lint/suspicious/noExplicitAny: cross-platform response type; varies per entry point
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
export interface CookieJarLike {
getCookies(url: URL): { name: string; value: string }[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
export type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: { WITH_CREDENTIALS?: boolean };
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
+31
-64
{
"name": "@aptos-labs/aptos-client",
"type": "module",
"description": "Client package for accessing the Aptos network API.",

@@ -12,69 +13,44 @@ "packageManager": "pnpm@10.30.1",

"deno": {
"types": "./dist/fetch/index.fetch.d.mts",
"import": "./dist/fetch/index.fetch.mjs"
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
},
"bun": {
"types": "./dist/fetch/index.fetch.d.mts",
"import": "./dist/fetch/index.fetch.mjs"
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
},
"workerd": {
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
},
"edge-light": {
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
},
"browser": {
"import": {
"types": "./dist/browser/index.browser.d.mts",
"default": "./dist/browser/index.browser.mjs"
},
"require": {
"types": "./dist/browser/index.browser.d.ts",
"default": "./dist/browser/index.browser.js"
}
"types": "./dist/index.browser.d.ts",
"default": "./dist/index.browser.js"
},
"react-native": {
"import": {
"types": "./dist/fetch/index.fetch.d.mts",
"default": "./dist/fetch/index.fetch.mjs"
},
"require": {
"types": "./dist/fetch/index.fetch.d.ts",
"default": "./dist/fetch/index.fetch.js"
}
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
},
"node": {
"import": {
"types": "./dist/node/index.node.d.mts",
"default": "./dist/node/index.node.mjs"
},
"require": {
"types": "./dist/node/index.node.d.ts",
"default": "./dist/node/index.node.js"
}
"types": "./dist/index.node.d.ts",
"default": "./dist/index.node.js"
},
"default": {
"import": {
"types": "./dist/fetch/index.fetch.d.mts",
"default": "./dist/fetch/index.fetch.mjs"
},
"require": {
"types": "./dist/fetch/index.fetch.d.ts",
"default": "./dist/fetch/index.fetch.js"
}
"types": "./dist/index.fetch.d.ts",
"default": "./dist/index.fetch.js"
}
}
},
"browser": {
"./dist/node/index.node.mjs": "./dist/browser/index.browser.mjs",
"./dist/node/index.node.js": "./dist/browser/index.browser.js"
},
"react-native": {
"./dist/node/index.node.mjs": "./dist/fetch/index.fetch.mjs",
"./dist/node/index.node.js": "./dist/fetch/index.fetch.js"
},
"main": "./dist/node/index.node.js",
"module": "./dist/node/index.node.mjs",
"sideEffects": false,
"types": "./dist/node/index.node.d.ts",
"types": "./dist/index.node.d.ts",
"files": [
"./dist/"
"dist",
"src"
],
"scripts": {
"build:clean": "rm -rf dist",
"build": "pnpm build:clean && tsup",
"build": "pnpm build:clean && tsc --project tsconfig.build.json",
"test": "tsx --test --test-force-exit test/node.test.ts test/fetch.test.ts test/browser.test.ts test/cookieJar.test.ts",

@@ -107,22 +83,13 @@ "test:node": "tsx --test --test-force-exit test/node.test.ts",

],
"peerDependencies": {
"undici": "^7.24.1"
"dependencies": {
"undici": "^7.25.0"
},
"peerDependenciesMeta": {
"undici": {
"optional": true
}
},
"devDependencies": {
"@biomejs/biome": "^2.4.6",
"@types/node": "^22.19.15",
"@types/node": "^22.19.17",
"esbuild": "^0.28.0",
"tsx": "^4.21.0",
"esbuild": "^0.27.4",
"tsup": "^8.5.1",
"typescript": "^5.9.3",
"undici": "^7.24.1",
"picomatch": "^4.0.4",
"brace-expansion": "2.0.3"
"typescript": "^6.0.2"
},
"version": "3.0.2"
"version": "4.0.0"
}

@@ -26,8 +26,2 @@ ![License][github-license]

`undici` is an optional peer dependency — only needed in Node.js:
```bash
npm install undici
```
## Usage

@@ -67,2 +61,4 @@

| `bun` | `index.fetch.ts` | Automatic | — |
| `workerd` | `index.fetch.ts` | Automatic | Cloudflare Workers |
| `edge-light` | `index.fetch.ts` | Automatic | Vercel Edge Functions |
| `default` | `index.fetch.ts` | Depends on runtime | Fallback for unknown runtimes |

@@ -91,3 +87,3 @@

response?: any;
headers?: any;
headers?: Record<string, string | string[]>;
};

@@ -94,0 +90,0 @@ ```

/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*/
declare function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { bcsRequest, aptosClient as default, jsonRequest };
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*/
declare function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { bcsRequest, aptosClient as default, jsonRequest };
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.browser.ts
var index_browser_exports = {};
__export(index_browser_exports, {
bcsRequest: () => bcsRequest,
default: () => aptosClient,
jsonRequest: () => jsonRequest
});
module.exports = __toCommonJS(index_browser_exports);
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.browser.ts
var http2Warned = false;
async function aptosClient(options) {
return jsonRequest(options);
}
async function jsonRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
async function bcsRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== void 0) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== void 0) {
headers.set(key, String(value));
}
}
const body = serializeBody(options.body);
if (body !== void 0) {
applyJsonContentType(options.body, headers);
}
const credentials = options.overrides?.WITH_CREDENTIALS === false ? "omit" : "include";
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body,
credentials
};
const requestUrl = buildUrl(options.url, options.params);
return { requestUrl: requestUrl.toString(), requestConfig };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
bcsRequest,
jsonRequest
});
//# sourceMappingURL=index.browser.js.map
{"version":3,"sources":["../../src/index.browser.ts","../../src/shared.ts"],"sourcesContent":["/**\n * Browser HTTP client using the native `fetch()` API.\n *\n * @remarks\n * Selected via the `\"browser\"` export condition. HTTP/2 negotiation is\n * handled by the browser engine — the {@link AptosClientRequest.http2 | http2}\n * option is ignored. Cookie handling is delegated to the browser; this entry\n * point does not use a {@link CookieJar}.\n *\n * The `credentials` mode on each request is controlled via\n * `overrides.WITH_CREDENTIALS` (`false` → `\"omit\"`,\n * default/`true` → `\"include\"`).\n *\n * @module index.browser\n */\nimport { applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody } from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse } from \"./types\";\n\nlet http2Warned = false;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n */\nexport default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest<Res>(options);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n */\nexport async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n const { requestUrl, requestConfig } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n const data = await parseJsonSafely(res);\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param options - Request configuration.\n */\nexport async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n const { requestUrl, requestConfig } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n const data = await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/** Build the URL and `RequestInit` from the caller's options. @internal */\nfunction buildRequest(options: AptosClientRequest) {\n if (options.method !== \"GET\" && options.method !== \"POST\") {\n throw new Error(`Unsupported method: ${options.method}`);\n }\n\n if (!http2Warned && options.http2 !== undefined) {\n http2Warned = true;\n console.warn(\"[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.\");\n }\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(options?.headers ?? {})) {\n if (value !== undefined) {\n headers.set(key, String(value));\n }\n }\n\n const body = serializeBody(options.body);\n if (body !== undefined) {\n applyJsonContentType(options.body, headers);\n }\n\n const credentials: RequestCredentials = options.overrides?.WITH_CREDENTIALS === false ? \"omit\" : \"include\";\n\n const requestConfig: RequestInit = {\n method: options.method,\n headers: headersToRecord(headers) as Record<string, string>,\n body,\n credentials,\n };\n\n const requestUrl = buildUrl(options.url, options.params);\n\n return { requestUrl: requestUrl.toString(), requestConfig };\n}\n","/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n"],"mappings":"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","names":[]}
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.browser.ts
var http2Warned = false;
async function aptosClient(options) {
return jsonRequest(options);
}
async function jsonRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
async function bcsRequest(options) {
const { requestUrl, requestConfig } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== void 0) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== void 0) {
headers.set(key, String(value));
}
}
const body = serializeBody(options.body);
if (body !== void 0) {
applyJsonContentType(options.body, headers);
}
const credentials = options.overrides?.WITH_CREDENTIALS === false ? "omit" : "include";
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body,
credentials
};
const requestUrl = buildUrl(options.url, options.params);
return { requestUrl: requestUrl.toString(), requestConfig };
}
export {
bcsRequest,
aptosClient as default,
jsonRequest
};
//# sourceMappingURL=index.browser.mjs.map
{"version":3,"sources":["../../src/shared.ts","../../src/index.browser.ts"],"sourcesContent":["/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n","/**\n * Browser HTTP client using the native `fetch()` API.\n *\n * @remarks\n * Selected via the `\"browser\"` export condition. HTTP/2 negotiation is\n * handled by the browser engine — the {@link AptosClientRequest.http2 | http2}\n * option is ignored. Cookie handling is delegated to the browser; this entry\n * point does not use a {@link CookieJar}.\n *\n * The `credentials` mode on each request is controlled via\n * `overrides.WITH_CREDENTIALS` (`false` → `\"omit\"`,\n * default/`true` → `\"include\"`).\n *\n * @module index.browser\n */\nimport { applyJsonContentType, buildUrl, headersToRecord, parseJsonSafely, serializeBody } from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse } from \"./types\";\n\nlet http2Warned = false;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n */\nexport default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest<Res>(options);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n */\nexport async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n const { requestUrl, requestConfig } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n const data = await parseJsonSafely(res);\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param options - Request configuration.\n */\nexport async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n const { requestUrl, requestConfig } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n const data = await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/** Build the URL and `RequestInit` from the caller's options. @internal */\nfunction buildRequest(options: AptosClientRequest) {\n if (options.method !== \"GET\" && options.method !== \"POST\") {\n throw new Error(`Unsupported method: ${options.method}`);\n }\n\n if (!http2Warned && options.http2 !== undefined) {\n http2Warned = true;\n console.warn(\"[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.\");\n }\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(options?.headers ?? {})) {\n if (value !== undefined) {\n headers.set(key, String(value));\n }\n }\n\n const body = serializeBody(options.body);\n if (body !== undefined) {\n applyJsonContentType(options.body, headers);\n }\n\n const credentials: RequestCredentials = options.overrides?.WITH_CREDENTIALS === false ? \"omit\" : \"include\";\n\n const requestConfig: RequestInit = {\n method: options.method,\n headers: headersToRecord(headers) as Record<string, string>,\n body,\n credentials,\n };\n\n const requestUrl = buildUrl(options.url, options.params);\n\n return { requestUrl: requestUrl.toString(), requestConfig };\n}\n"],"mappings":"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","names":[]}
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/** A parsed cookie with optional attributes. */
interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
declare class CookieJar {
private jar;
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(jar?: Map<string, Cookie[]>);
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string): void;
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[];
/** Remove all stored cookies. Useful for test isolation. */
clear(): void;
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie;
}
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
declare function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { CookieJar, type CookieJarLike, bcsRequest, aptosClient as default, jsonRequest };
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/** A parsed cookie with optional attributes. */
interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
declare class CookieJar {
private jar;
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(jar?: Map<string, Cookie[]>);
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string): void;
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[];
/** Remove all stored cookies. Useful for test isolation. */
clear(): void;
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie;
}
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
declare function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
declare function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
declare function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { CookieJar, type CookieJarLike, bcsRequest, aptosClient as default, jsonRequest };
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.fetch.ts
var index_fetch_exports = {};
__export(index_fetch_exports, {
CookieJar: () => CookieJar,
bcsRequest: () => bcsRequest,
default: () => aptosClient,
jsonRequest: () => jsonRequest
});
module.exports = __toCommonJS(index_fetch_exports);
// src/cookieJar.ts
var CookieJar = class _CookieJar {
constructor(jar = /* @__PURE__ */ new Map()) {
this.jar = jar;
}
static MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static MAX_COOKIE_SIZE = 8192;
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url, cookieStr) {
if (cookieStr.length > _CookieJar.MAX_COOKIE_SIZE) {
return;
}
let cookie;
try {
cookie = _CookieJar.parse(cookieStr);
} catch {
return;
}
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
while (existing.length >= _CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url) {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = /* @__PURE__ */ new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now) return false;
return true;
});
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
} else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str) {
const parts = str.split(";").map((part) => part.trim());
let cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value
};
} else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? void 0 : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax") cookie.sameSite = "Lax";
else if (normalized === "none") cookie.sameSite = "None";
else if (normalized === "strict") cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
};
var TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name) {
return TOKEN_RE.test(name);
}
function hasControlChars(str) {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 31 || code === 127) return true;
}
return false;
}
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function applyCookiesToHeaders(headers, url, jar) {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
function storeResponseCookies(url, headers, jar) {
if (typeof headers.getSetCookie !== "function") return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.fetch.ts
var defaultCookieJar = new CookieJar();
var http2Warned = false;
async function aptosClient(options) {
return jsonRequest(options);
}
async function jsonRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
async function bcsRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== void 0) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const jar = options.cookieJar ?? defaultCookieJar;
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== void 0) {
headers.set(key, String(value));
}
}
const requestUrl = buildUrl(options.url, options.params);
applyCookiesToHeaders(headers, requestUrl, jar);
const body = serializeBody(options.body);
if (body !== void 0) {
applyJsonContentType(options.body, headers);
}
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body
};
return { requestUrl: requestUrl.toString(), requestConfig, jar };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CookieJar,
bcsRequest,
jsonRequest
});
//# sourceMappingURL=index.fetch.js.map
{"version":3,"sources":["../../src/index.fetch.ts","../../src/cookieJar.ts","../../src/shared.ts"],"sourcesContent":["/**\n * Fetch-based HTTP client for runtimes with native HTTP/2 support.\n *\n * @remarks\n * Used by Deno, Bun, React Native, and any other runtime that provides a\n * spec-compliant `fetch()`. These runtimes negotiate HTTP/2 automatically\n * via ALPN, so the {@link AptosClientRequest.http2 | http2} option is\n * ignored.\n *\n * @module index.fetch\n */\nimport { CookieJar } from \"./cookieJar\";\nimport {\n applyCookiesToHeaders,\n applyJsonContentType,\n buildUrl,\n headersToRecord,\n parseJsonSafely,\n serializeBody,\n storeResponseCookies,\n} from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse } from \"./types\";\n\nexport { CookieJar } from \"./cookieJar\";\nexport type { CookieJarLike } from \"./types\";\n\nconst defaultCookieJar = new CookieJar();\n\nlet http2Warned = false;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n *\n * @example\n * ```ts\n * import aptosClient from \"@aptos-labs/aptos-client\";\n *\n * const { data } = await aptosClient<{ chain_id: number }>({\n * url: \"https://fullnode.mainnet.aptoslabs.com/v1\",\n * method: \"GET\",\n * });\n * ```\n */\nexport default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest<Res>(options);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n */\nexport async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n const { requestUrl, requestConfig, jar } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n storeResponseCookies(new URL(requestUrl), res.headers, jar);\n const data = await parseJsonSafely(res);\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param options - Request configuration.\n */\nexport async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n const { requestUrl, requestConfig, jar } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n storeResponseCookies(new URL(requestUrl), res.headers, jar);\n const data = await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/** Build the URL and `RequestInit` from the caller's options. @internal */\nfunction buildRequest(options: AptosClientRequest) {\n if (options.method !== \"GET\" && options.method !== \"POST\") {\n throw new Error(`Unsupported method: ${options.method}`);\n }\n\n if (!http2Warned && options.http2 !== undefined) {\n http2Warned = true;\n console.warn(\"[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.\");\n }\n\n const jar = options.cookieJar ?? defaultCookieJar;\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(options?.headers ?? {})) {\n if (value !== undefined) {\n headers.set(key, String(value));\n }\n }\n\n const requestUrl = buildUrl(options.url, options.params);\n\n applyCookiesToHeaders(headers, requestUrl, jar);\n\n const body = serializeBody(options.body);\n if (body !== undefined) {\n applyJsonContentType(options.body, headers);\n }\n\n const requestConfig: RequestInit = {\n method: options.method,\n headers: headersToRecord(headers) as Record<string, string>,\n body,\n };\n\n return { requestUrl: requestUrl.toString(), requestConfig, jar };\n}\n","/** A parsed cookie with optional attributes. */\ninterface Cookie {\n name: string;\n value: string;\n expires?: Date;\n sameSite?: \"Lax\" | \"None\" | \"Strict\";\n secure?: boolean;\n httpOnly?: boolean;\n}\n\n/**\n * Minimal, origin-scoped cookie jar used by the Node and fetch entry points.\n *\n * @remarks\n * Cookies are keyed by origin (scheme + host + port). Expired cookies are\n * filtered out lazily when {@link getCookies} is called. The browser entry\n * point delegates cookie handling to the browser engine and does not use\n * this class.\n *\n * **Note:** A single module-level `CookieJar` instance is shared across all\n * requests in the same process. In multi-tenant server-side environments,\n * create a separate instance and pass it via {@link AptosClientRequest.cookieJar}\n * to avoid cross-request cookie leakage.\n */\nexport class CookieJar {\n static readonly MAX_COOKIES_PER_ORIGIN = 50;\n /** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */\n static readonly MAX_COOKIE_SIZE = 8192;\n\n constructor(private jar = new Map<string, Cookie[]>()) {}\n\n /**\n * Store a `Set-Cookie` header value for the given URL's origin.\n *\n * @param url - The URL the response was received from.\n * @param cookieStr - Raw `Set-Cookie` header string.\n */\n setCookie(url: URL, cookieStr: string) {\n if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {\n return; // Silently drop oversized cookies\n }\n\n let cookie: Cookie;\n try {\n cookie = CookieJar.parse(cookieStr);\n } catch {\n return; // Silently skip malformed cookies, matching browser behavior\n }\n\n // RFC 6265bis: SameSite=None requires the Secure attribute\n if (cookie.sameSite === \"None\" && !cookie.secure) {\n return;\n }\n\n const key = url.origin.toLowerCase();\n if (!this.jar.has(key)) {\n this.jar.set(key, []);\n }\n\n const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];\n // Evict oldest cookies if we're at the per-origin cap\n while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {\n existing.shift();\n }\n this.jar.set(key, [...existing, cookie]);\n }\n\n /**\n * Return all non-expired cookies for the given URL's origin.\n *\n * @param url - The URL to match cookies against.\n * @returns An array of {@link Cookie} objects (may be empty).\n */\n getCookies(url: URL): Cookie[] {\n const key = url.origin.toLowerCase();\n const cookies = this.jar.get(key);\n if (!cookies) {\n return [];\n }\n\n const now = new Date();\n const isSecure = url.protocol === \"https:\";\n const live = cookies.filter((cookie) => {\n if (cookie.expires && cookie.expires <= now) return false;\n return true;\n });\n\n // Write back to evict expired cookies from storage\n if (live.length !== cookies.length) {\n if (live.length === 0) {\n this.jar.delete(key);\n } else {\n this.jar.set(key, live);\n }\n }\n\n return isSecure ? live : live.filter((cookie) => !cookie.secure);\n }\n\n /** Remove all stored cookies. Useful for test isolation. */\n clear() {\n this.jar.clear();\n }\n\n /**\n * Parse a raw `Set-Cookie` header string into a {@link Cookie} object.\n *\n * @param str - Raw `Set-Cookie` header value.\n * @returns Parsed cookie.\n * @throws If the cookie is malformed or contains control characters.\n */\n static parse(str: string): Cookie {\n const parts = str.split(\";\").map((part) => part.trim());\n\n let cookie: Cookie;\n\n if (parts.length > 0) {\n const eqIdx = parts[0].indexOf(\"=\");\n if (eqIdx < 1) {\n throw new Error(\"Invalid cookie\");\n }\n const name = parts[0].slice(0, eqIdx);\n const value = parts[0].slice(eqIdx + 1);\n\n // RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token\n if (!isValidTokenName(name)) {\n throw new Error(\"Invalid cookie: name contains invalid characters\");\n }\n // Reject control characters in value that could enable header injection\n if (hasControlChars(value)) {\n throw new Error(\"Invalid cookie: value contains control characters\");\n }\n\n cookie = {\n name,\n value,\n };\n } else {\n throw new Error(\"Invalid cookie\");\n }\n\n parts.slice(1).forEach((part) => {\n const attrEqIdx = part.indexOf(\"=\");\n const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);\n const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);\n if (!name.trim()) {\n throw new Error(\"Invalid cookie\");\n }\n\n const nameLow = name.toLowerCase();\n // Only strip quotes when both opening and closing characters match\n let val = value;\n if (value && value.length >= 2) {\n const first = value.charAt(0);\n const last = value.charAt(value.length - 1);\n if ((first === '\"' || first === \"'\") && first === last) {\n val = value.slice(1, -1);\n }\n }\n if (nameLow === \"expires\" && val) {\n const date = new Date(val);\n if (!Number.isNaN(date.getTime())) {\n cookie.expires = date;\n }\n }\n if (nameLow === \"samesite\") {\n const normalized = val?.toLowerCase();\n if (normalized === \"lax\") cookie.sameSite = \"Lax\";\n else if (normalized === \"none\") cookie.sameSite = \"None\";\n else if (normalized === \"strict\") cookie.sameSite = \"Strict\";\n }\n if (nameLow === \"secure\") {\n cookie.secure = true;\n }\n if (nameLow === \"httponly\") {\n cookie.httpOnly = true;\n }\n });\n\n return cookie;\n }\n}\n\n/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */\nconst TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\nfunction isValidTokenName(name: string): boolean {\n return TOKEN_RE.test(name);\n}\n\n/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */\nfunction hasControlChars(str: string): boolean {\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n","/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n"],"mappings":"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","names":[]}
// src/cookieJar.ts
var CookieJar = class _CookieJar {
constructor(jar = /* @__PURE__ */ new Map()) {
this.jar = jar;
}
static MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static MAX_COOKIE_SIZE = 8192;
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url, cookieStr) {
if (cookieStr.length > _CookieJar.MAX_COOKIE_SIZE) {
return;
}
let cookie;
try {
cookie = _CookieJar.parse(cookieStr);
} catch {
return;
}
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
while (existing.length >= _CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url) {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = /* @__PURE__ */ new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now) return false;
return true;
});
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
} else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str) {
const parts = str.split(";").map((part) => part.trim());
let cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value
};
} else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? void 0 : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax") cookie.sameSite = "Lax";
else if (normalized === "none") cookie.sameSite = "None";
else if (normalized === "strict") cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
};
var TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name) {
return TOKEN_RE.test(name);
}
function hasControlChars(str) {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 31 || code === 127) return true;
}
return false;
}
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function applyCookiesToHeaders(headers, url, jar) {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
function storeResponseCookies(url, headers, jar) {
if (typeof headers.getSetCookie !== "function") return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.fetch.ts
var defaultCookieJar = new CookieJar();
var http2Warned = false;
async function aptosClient(options) {
return jsonRequest(options);
}
async function jsonRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
async function bcsRequest(options) {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig
};
}
function buildRequest(options) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== void 0) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const jar = options.cookieJar ?? defaultCookieJar;
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== void 0) {
headers.set(key, String(value));
}
}
const requestUrl = buildUrl(options.url, options.params);
applyCookiesToHeaders(headers, requestUrl, jar);
const body = serializeBody(options.body);
if (body !== void 0) {
applyJsonContentType(options.body, headers);
}
const requestConfig = {
method: options.method,
headers: headersToRecord(headers),
body
};
return { requestUrl: requestUrl.toString(), requestConfig, jar };
}
export {
CookieJar,
bcsRequest,
aptosClient as default,
jsonRequest
};
//# sourceMappingURL=index.fetch.mjs.map
{"version":3,"sources":["../../src/cookieJar.ts","../../src/shared.ts","../../src/index.fetch.ts"],"sourcesContent":["/** A parsed cookie with optional attributes. */\ninterface Cookie {\n name: string;\n value: string;\n expires?: Date;\n sameSite?: \"Lax\" | \"None\" | \"Strict\";\n secure?: boolean;\n httpOnly?: boolean;\n}\n\n/**\n * Minimal, origin-scoped cookie jar used by the Node and fetch entry points.\n *\n * @remarks\n * Cookies are keyed by origin (scheme + host + port). Expired cookies are\n * filtered out lazily when {@link getCookies} is called. The browser entry\n * point delegates cookie handling to the browser engine and does not use\n * this class.\n *\n * **Note:** A single module-level `CookieJar` instance is shared across all\n * requests in the same process. In multi-tenant server-side environments,\n * create a separate instance and pass it via {@link AptosClientRequest.cookieJar}\n * to avoid cross-request cookie leakage.\n */\nexport class CookieJar {\n static readonly MAX_COOKIES_PER_ORIGIN = 50;\n /** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */\n static readonly MAX_COOKIE_SIZE = 8192;\n\n constructor(private jar = new Map<string, Cookie[]>()) {}\n\n /**\n * Store a `Set-Cookie` header value for the given URL's origin.\n *\n * @param url - The URL the response was received from.\n * @param cookieStr - Raw `Set-Cookie` header string.\n */\n setCookie(url: URL, cookieStr: string) {\n if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {\n return; // Silently drop oversized cookies\n }\n\n let cookie: Cookie;\n try {\n cookie = CookieJar.parse(cookieStr);\n } catch {\n return; // Silently skip malformed cookies, matching browser behavior\n }\n\n // RFC 6265bis: SameSite=None requires the Secure attribute\n if (cookie.sameSite === \"None\" && !cookie.secure) {\n return;\n }\n\n const key = url.origin.toLowerCase();\n if (!this.jar.has(key)) {\n this.jar.set(key, []);\n }\n\n const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];\n // Evict oldest cookies if we're at the per-origin cap\n while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {\n existing.shift();\n }\n this.jar.set(key, [...existing, cookie]);\n }\n\n /**\n * Return all non-expired cookies for the given URL's origin.\n *\n * @param url - The URL to match cookies against.\n * @returns An array of {@link Cookie} objects (may be empty).\n */\n getCookies(url: URL): Cookie[] {\n const key = url.origin.toLowerCase();\n const cookies = this.jar.get(key);\n if (!cookies) {\n return [];\n }\n\n const now = new Date();\n const isSecure = url.protocol === \"https:\";\n const live = cookies.filter((cookie) => {\n if (cookie.expires && cookie.expires <= now) return false;\n return true;\n });\n\n // Write back to evict expired cookies from storage\n if (live.length !== cookies.length) {\n if (live.length === 0) {\n this.jar.delete(key);\n } else {\n this.jar.set(key, live);\n }\n }\n\n return isSecure ? live : live.filter((cookie) => !cookie.secure);\n }\n\n /** Remove all stored cookies. Useful for test isolation. */\n clear() {\n this.jar.clear();\n }\n\n /**\n * Parse a raw `Set-Cookie` header string into a {@link Cookie} object.\n *\n * @param str - Raw `Set-Cookie` header value.\n * @returns Parsed cookie.\n * @throws If the cookie is malformed or contains control characters.\n */\n static parse(str: string): Cookie {\n const parts = str.split(\";\").map((part) => part.trim());\n\n let cookie: Cookie;\n\n if (parts.length > 0) {\n const eqIdx = parts[0].indexOf(\"=\");\n if (eqIdx < 1) {\n throw new Error(\"Invalid cookie\");\n }\n const name = parts[0].slice(0, eqIdx);\n const value = parts[0].slice(eqIdx + 1);\n\n // RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token\n if (!isValidTokenName(name)) {\n throw new Error(\"Invalid cookie: name contains invalid characters\");\n }\n // Reject control characters in value that could enable header injection\n if (hasControlChars(value)) {\n throw new Error(\"Invalid cookie: value contains control characters\");\n }\n\n cookie = {\n name,\n value,\n };\n } else {\n throw new Error(\"Invalid cookie\");\n }\n\n parts.slice(1).forEach((part) => {\n const attrEqIdx = part.indexOf(\"=\");\n const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);\n const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);\n if (!name.trim()) {\n throw new Error(\"Invalid cookie\");\n }\n\n const nameLow = name.toLowerCase();\n // Only strip quotes when both opening and closing characters match\n let val = value;\n if (value && value.length >= 2) {\n const first = value.charAt(0);\n const last = value.charAt(value.length - 1);\n if ((first === '\"' || first === \"'\") && first === last) {\n val = value.slice(1, -1);\n }\n }\n if (nameLow === \"expires\" && val) {\n const date = new Date(val);\n if (!Number.isNaN(date.getTime())) {\n cookie.expires = date;\n }\n }\n if (nameLow === \"samesite\") {\n const normalized = val?.toLowerCase();\n if (normalized === \"lax\") cookie.sameSite = \"Lax\";\n else if (normalized === \"none\") cookie.sameSite = \"None\";\n else if (normalized === \"strict\") cookie.sameSite = \"Strict\";\n }\n if (nameLow === \"secure\") {\n cookie.secure = true;\n }\n if (nameLow === \"httponly\") {\n cookie.httpOnly = true;\n }\n });\n\n return cookie;\n }\n}\n\n/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */\nconst TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\nfunction isValidTokenName(name: string): boolean {\n return TOKEN_RE.test(name);\n}\n\n/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */\nfunction hasControlChars(str: string): boolean {\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n","/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n","/**\n * Fetch-based HTTP client for runtimes with native HTTP/2 support.\n *\n * @remarks\n * Used by Deno, Bun, React Native, and any other runtime that provides a\n * spec-compliant `fetch()`. These runtimes negotiate HTTP/2 automatically\n * via ALPN, so the {@link AptosClientRequest.http2 | http2} option is\n * ignored.\n *\n * @module index.fetch\n */\nimport { CookieJar } from \"./cookieJar\";\nimport {\n applyCookiesToHeaders,\n applyJsonContentType,\n buildUrl,\n headersToRecord,\n parseJsonSafely,\n serializeBody,\n storeResponseCookies,\n} from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse } from \"./types\";\n\nexport { CookieJar } from \"./cookieJar\";\nexport type { CookieJarLike } from \"./types\";\n\nconst defaultCookieJar = new CookieJar();\n\nlet http2Warned = false;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n *\n * @example\n * ```ts\n * import aptosClient from \"@aptos-labs/aptos-client\";\n *\n * const { data } = await aptosClient<{ chain_id: number }>({\n * url: \"https://fullnode.mainnet.aptoslabs.com/v1\",\n * method: \"GET\",\n * });\n * ```\n */\nexport default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest<Res>(options);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param options - Request configuration.\n */\nexport async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n const { requestUrl, requestConfig, jar } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n storeResponseCookies(new URL(requestUrl), res.headers, jar);\n const data = await parseJsonSafely(res);\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param options - Request configuration.\n */\nexport async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n const { requestUrl, requestConfig, jar } = buildRequest(options);\n\n const res = await fetch(requestUrl, requestConfig);\n storeResponseCookies(new URL(requestUrl), res.headers, jar);\n const data = await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n headers: headersToRecord(res.headers),\n config: requestConfig,\n };\n}\n\n/** Build the URL and `RequestInit` from the caller's options. @internal */\nfunction buildRequest(options: AptosClientRequest) {\n if (options.method !== \"GET\" && options.method !== \"POST\") {\n throw new Error(`Unsupported method: ${options.method}`);\n }\n\n if (!http2Warned && options.http2 !== undefined) {\n http2Warned = true;\n console.warn(\"[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.\");\n }\n\n const jar = options.cookieJar ?? defaultCookieJar;\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(options?.headers ?? {})) {\n if (value !== undefined) {\n headers.set(key, String(value));\n }\n }\n\n const requestUrl = buildUrl(options.url, options.params);\n\n applyCookiesToHeaders(headers, requestUrl, jar);\n\n const body = serializeBody(options.body);\n if (body !== undefined) {\n applyJsonContentType(options.body, headers);\n }\n\n const requestConfig: RequestInit = {\n method: options.method,\n headers: headersToRecord(headers) as Record<string, string>,\n body,\n };\n\n return { requestUrl: requestUrl.toString(), requestConfig, jar };\n}\n"],"mappings":"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","names":[]}
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/** A parsed cookie with optional attributes. */
interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
declare class CookieJar {
private jar;
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(jar?: Map<string, Cookie[]>);
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string): void;
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[];
/** Remove all stored cookies. Useful for test isolation. */
clear(): void;
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie;
}
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
declare function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
*/
declare function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param requestOptions - Request configuration.
*/
declare function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { CookieJar, type CookieJarLike, bcsRequest, aptosClient as default, jsonRequest };
/**
* Response returned by all `aptosClient` entry points.
*
* @typeParam Res - The expected shape of the parsed response body.
* For {@link jsonRequest} this is the deserialized JSON object;
* for {@link bcsRequest} it is `ArrayBuffer`.
*/
type AptosClientResponse<Res> = {
/** HTTP status code (e.g. `200`, `404`). */
status: number;
/** HTTP reason phrase (e.g. `"OK"`, `"Not Found"`). */
statusText: string;
/** Parsed response body. */
data: Res;
/** The `RequestInit` (or undici equivalent) that was sent. */
config?: any;
/** Metadata about the outgoing request (Node entry point only). */
request?: any;
/** The raw `Response` object (Node entry point only). */
response?: any;
/** Response headers as a plain key-value record. */
headers?: Record<string, string | string[]>;
};
/**
* Minimal cookie jar interface for per-request cookie isolation.
*
* @remarks
* Implement this interface or use the {@link CookieJar} class exported by
* the Node and fetch entry points. The browser entry point ignores this
* option (cookies are managed by the browser engine).
*/
interface CookieJarLike {
getCookies(url: URL): {
name: string;
value: string;
}[];
setCookie(url: URL, cookieStr: string): void;
}
/**
* Options accepted by every `aptosClient` call.
*/
type AptosClientRequest = {
/** Fully-qualified URL of the Aptos API endpoint. */
url: string;
/** HTTP method — only `GET` and `POST` are supported. */
method: "GET" | "POST";
/**
* Request body. Objects are JSON-serialized; `Uint8Array` is sent as binary.
*
* @remarks
* Typed as `unknown` for compatibility with the SDK's generic
* `ClientRequest<Req>`. At runtime, values are handled as either
* `Uint8Array` (sent verbatim) or anything else (`JSON.stringify`).
*/
body?: unknown;
/** Query-string parameters appended to the URL. `bigint` values are stringified automatically. */
params?: Record<string, string | number | bigint | boolean | undefined>;
/** Additional HTTP headers merged into the request. */
headers?: Record<string, string | undefined>;
/**
* Runtime-specific overrides.
*
* @remarks
* In the **browser** entry point, `overrides.WITH_CREDENTIALS` controls the
* `credentials` option on the `fetch` call (`false` → `"omit"`,
* default/`true` → `"include"`).
*/
overrides?: {
WITH_CREDENTIALS?: boolean;
};
/**
* Enable or disable HTTP/2 negotiation.
*
* @defaultValue `true`
*
* @remarks
* Only effective in the **Node** entry point, where it maps to
* undici's `Agent({ allowH2 })`. In the **fetch**, **browser**, and
* **React Native** entry points the underlying runtime negotiates
* HTTP/2 automatically via ALPN — this option is ignored.
*/
http2?: boolean;
/**
* Override the module-level cookie jar for this request.
*
* @remarks
* By default, the Node and fetch entry points use a shared module-level
* `CookieJar` singleton. In multi-tenant or server-side environments,
* pass a per-request jar to prevent cross-request cookie leakage.
* The browser entry point ignores this option.
*/
cookieJar?: CookieJarLike;
};
/** A parsed cookie with optional attributes. */
interface Cookie {
name: string;
value: string;
expires?: Date;
sameSite?: "Lax" | "None" | "Strict";
secure?: boolean;
httpOnly?: boolean;
}
/**
* Minimal, origin-scoped cookie jar used by the Node and fetch entry points.
*
* @remarks
* Cookies are keyed by origin (scheme + host + port). Expired cookies are
* filtered out lazily when {@link getCookies} is called. The browser entry
* point delegates cookie handling to the browser engine and does not use
* this class.
*
* **Note:** A single module-level `CookieJar` instance is shared across all
* requests in the same process. In multi-tenant server-side environments,
* create a separate instance and pass it via {@link AptosClientRequest.cookieJar}
* to avoid cross-request cookie leakage.
*/
declare class CookieJar {
private jar;
static readonly MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static readonly MAX_COOKIE_SIZE = 8192;
constructor(jar?: Map<string, Cookie[]>);
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url: URL, cookieStr: string): void;
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url: URL): Cookie[];
/** Remove all stored cookies. Useful for test isolation. */
clear(): void;
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str: string): Cookie;
}
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
declare function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param requestOptions - Request configuration.
*/
declare function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>>;
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param requestOptions - Request configuration.
*/
declare function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>>;
export { CookieJar, type CookieJarLike, bcsRequest, aptosClient as default, jsonRequest };
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.node.ts
var index_node_exports = {};
__export(index_node_exports, {
CookieJar: () => CookieJar,
bcsRequest: () => bcsRequest,
default: () => aptosClient,
jsonRequest: () => jsonRequest
});
module.exports = __toCommonJS(index_node_exports);
var import_undici = require("undici");
// src/cookieJar.ts
var CookieJar = class _CookieJar {
constructor(jar = /* @__PURE__ */ new Map()) {
this.jar = jar;
}
static MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static MAX_COOKIE_SIZE = 8192;
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url, cookieStr) {
if (cookieStr.length > _CookieJar.MAX_COOKIE_SIZE) {
return;
}
let cookie;
try {
cookie = _CookieJar.parse(cookieStr);
} catch {
return;
}
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
while (existing.length >= _CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url) {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = /* @__PURE__ */ new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now) return false;
return true;
});
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
} else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str) {
const parts = str.split(";").map((part) => part.trim());
let cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value
};
} else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? void 0 : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax") cookie.sameSite = "Lax";
else if (normalized === "none") cookie.sameSite = "None";
else if (normalized === "strict") cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
};
var TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name) {
return TOKEN_RE.test(name);
}
function hasControlChars(str) {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 31 || code === 127) return true;
}
return false;
}
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function applyCookiesToHeaders(headers, url, jar) {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
function storeResponseCookies(url, headers, jar) {
if (typeof headers.getSetCookie !== "function") return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.node.ts
var defaultCookieJar = new CookieJar();
var dispatcherCache = /* @__PURE__ */ new Map();
var MAX_DISPATCHERS = 50;
async function aptosClient(requestOptions) {
return jsonRequest(requestOptions);
}
async function jsonRequest(requestOptions) {
return await doRequest(requestOptions, "json");
}
async function bcsRequest(requestOptions) {
return await doRequest(requestOptions, "arrayBuffer");
}
async function doRequest(requestOptions, mode) {
const { url, method, params, headers, body, http2 = true } = requestOptions;
const jar = requestOptions.cookieJar ?? defaultCookieJar;
if (method !== "GET" && method !== "POST") {
throw new Error(`Unsupported method: ${method}`);
}
const requestUrl = buildUrl(url, params);
const requestHeaders = buildHeaders(requestUrl, headers, jar);
const dispatcher = getDispatcher(requestUrl.origin, http2);
const init = {
method,
headers: requestHeaders,
dispatcher
};
const serialized = serializeBody(body);
if (serialized !== void 0) {
init.body = serialized;
applyJsonContentType(body, requestHeaders);
}
const res = await fetch(requestUrl, init);
storeResponseCookies(requestUrl, res.headers, jar);
const data = mode === "json" ? await parseJsonSafely(res) : await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
config: { ...init, headers: headersToRecord(requestHeaders) },
request: {
url: requestUrl.toString(),
method
},
response: res,
headers: headersToRecord(res.headers)
};
}
function getDispatcher(origin, http2) {
const key = `${origin}|h2=${http2}`;
const cached = dispatcherCache.get(key);
if (cached) {
dispatcherCache.delete(key);
dispatcherCache.set(key, cached);
return cached;
}
if (dispatcherCache.size >= MAX_DISPATCHERS) {
const oldest = dispatcherCache.keys().next().value;
dispatcherCache.get(oldest).destroy().catch(() => {
});
dispatcherCache.delete(oldest);
}
const agent = new import_undici.Agent({
allowH2: http2
});
dispatcherCache.set(key, agent);
return agent;
}
function buildHeaders(url, headers, jar) {
const result = new Headers();
for (const [key, value] of Object.entries(headers ?? {})) {
if (value !== void 0) {
result.set(key, String(value));
}
}
applyCookiesToHeaders(result, url, jar);
return result;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CookieJar,
bcsRequest,
jsonRequest
});
//# sourceMappingURL=index.node.js.map
{"version":3,"sources":["../../src/index.node.ts","../../src/cookieJar.ts","../../src/shared.ts"],"sourcesContent":["/**\n * Node.js HTTP client backed by {@link https://undici.nodejs.org | undici}.\n *\n * @remarks\n * This entry point is selected when the package is imported from Node.js\n * (via the `\"node\"` export condition). It uses undici's `Agent` with\n * configurable HTTP/2 support (`allowH2`). Agents are cached per origin\n * so connections are reused across requests to the same host.\n *\n * @module index.node\n */\nimport { Agent } from \"undici\";\nimport { CookieJar } from \"./cookieJar\";\nimport {\n applyCookiesToHeaders,\n applyJsonContentType,\n buildUrl,\n headersToRecord,\n parseJsonSafely,\n serializeBody,\n storeResponseCookies,\n} from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse, CookieJarLike } from \"./types\";\n\nexport { CookieJar } from \"./cookieJar\";\nexport type { CookieJarLike } from \"./types\";\n\nconst defaultCookieJar = new CookieJar();\n\n/** One dispatcher per origin + HTTP/2 mode for connection reuse. */\nconst dispatcherCache = new Map<string, Agent>();\nconst MAX_DISPATCHERS = 50;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param requestOptions - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n *\n * @example\n * ```ts\n * import aptosClient from \"@aptos-labs/aptos-client\";\n *\n * const { data } = await aptosClient<{ chain_id: number }>({\n * url: \"https://fullnode.mainnet.aptoslabs.com/v1\",\n * method: \"GET\",\n * });\n * ```\n */\nexport default async function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest(requestOptions);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param requestOptions - Request configuration.\n */\nexport async function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return await doRequest(requestOptions, \"json\");\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param requestOptions - Request configuration.\n */\nexport async function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n return await doRequest(requestOptions, \"arrayBuffer\");\n}\n\n/** @internal */\ntype ResponseMode = \"json\" | \"arrayBuffer\";\n\n/**\n * Core request handler shared by {@link jsonRequest} and {@link bcsRequest}.\n * @internal\n */\nasync function doRequest<Res>(\n requestOptions: AptosClientRequest,\n mode: ResponseMode,\n): Promise<AptosClientResponse<Res>> {\n const { url, method, params, headers, body, http2 = true } = requestOptions;\n const jar = requestOptions.cookieJar ?? defaultCookieJar;\n\n if (method !== \"GET\" && method !== \"POST\") {\n throw new Error(`Unsupported method: ${method}`);\n }\n\n const requestUrl = buildUrl(url, params);\n const requestHeaders = buildHeaders(requestUrl, headers, jar);\n const dispatcher = getDispatcher(requestUrl.origin, http2);\n\n const init: RequestInit & { dispatcher?: Agent } = {\n method,\n headers: requestHeaders,\n dispatcher,\n };\n\n const serialized = serializeBody(body);\n if (serialized !== undefined) {\n init.body = serialized;\n applyJsonContentType(body, requestHeaders);\n }\n\n const res = await fetch(requestUrl, init);\n\n storeResponseCookies(requestUrl, res.headers, jar);\n\n const data = mode === \"json\" ? await parseJsonSafely(res) : await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n config: { ...init, headers: headersToRecord(requestHeaders) },\n request: {\n url: requestUrl.toString(),\n method,\n },\n response: res,\n headers: headersToRecord(res.headers),\n };\n}\n\n/**\n * Return a cached undici `Agent` for the given origin, creating one if needed.\n *\n * @param origin - URL origin (scheme + host + port).\n * @param http2 - Whether to enable HTTP/2 via ALPN (`allowH2`).\n * @internal\n */\nfunction getDispatcher(origin: string, http2: boolean): Agent {\n const key = `${origin}|h2=${http2}`;\n const cached = dispatcherCache.get(key);\n if (cached) {\n // Move to end of Map (most-recently-used)\n dispatcherCache.delete(key);\n dispatcherCache.set(key, cached);\n return cached;\n }\n\n // Evict oldest entry if cache is full\n if (dispatcherCache.size >= MAX_DISPATCHERS) {\n // biome-ignore lint/style/noNonNullAssertion: cache size check guarantees entry exists\n const oldest = dispatcherCache.keys().next().value!;\n // biome-ignore lint/style/noNonNullAssertion: oldest key was just retrieved from cache\n dispatcherCache\n .get(oldest)!\n .destroy()\n .catch(() => {});\n dispatcherCache.delete(oldest);\n }\n\n const agent = new Agent({\n allowH2: http2,\n });\n\n dispatcherCache.set(key, agent);\n return agent;\n}\n\n/**\n * Merge caller-supplied headers with cookies from the jar.\n * @internal\n */\nfunction buildHeaders(url: URL, headers: AptosClientRequest[\"headers\"] | undefined, jar: CookieJarLike): Headers {\n const result = new Headers();\n\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (value !== undefined) {\n result.set(key, String(value));\n }\n }\n\n applyCookiesToHeaders(result, url, jar);\n\n return result;\n}\n","/** A parsed cookie with optional attributes. */\ninterface Cookie {\n name: string;\n value: string;\n expires?: Date;\n sameSite?: \"Lax\" | \"None\" | \"Strict\";\n secure?: boolean;\n httpOnly?: boolean;\n}\n\n/**\n * Minimal, origin-scoped cookie jar used by the Node and fetch entry points.\n *\n * @remarks\n * Cookies are keyed by origin (scheme + host + port). Expired cookies are\n * filtered out lazily when {@link getCookies} is called. The browser entry\n * point delegates cookie handling to the browser engine and does not use\n * this class.\n *\n * **Note:** A single module-level `CookieJar` instance is shared across all\n * requests in the same process. In multi-tenant server-side environments,\n * create a separate instance and pass it via {@link AptosClientRequest.cookieJar}\n * to avoid cross-request cookie leakage.\n */\nexport class CookieJar {\n static readonly MAX_COOKIES_PER_ORIGIN = 50;\n /** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */\n static readonly MAX_COOKIE_SIZE = 8192;\n\n constructor(private jar = new Map<string, Cookie[]>()) {}\n\n /**\n * Store a `Set-Cookie` header value for the given URL's origin.\n *\n * @param url - The URL the response was received from.\n * @param cookieStr - Raw `Set-Cookie` header string.\n */\n setCookie(url: URL, cookieStr: string) {\n if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {\n return; // Silently drop oversized cookies\n }\n\n let cookie: Cookie;\n try {\n cookie = CookieJar.parse(cookieStr);\n } catch {\n return; // Silently skip malformed cookies, matching browser behavior\n }\n\n // RFC 6265bis: SameSite=None requires the Secure attribute\n if (cookie.sameSite === \"None\" && !cookie.secure) {\n return;\n }\n\n const key = url.origin.toLowerCase();\n if (!this.jar.has(key)) {\n this.jar.set(key, []);\n }\n\n const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];\n // Evict oldest cookies if we're at the per-origin cap\n while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {\n existing.shift();\n }\n this.jar.set(key, [...existing, cookie]);\n }\n\n /**\n * Return all non-expired cookies for the given URL's origin.\n *\n * @param url - The URL to match cookies against.\n * @returns An array of {@link Cookie} objects (may be empty).\n */\n getCookies(url: URL): Cookie[] {\n const key = url.origin.toLowerCase();\n const cookies = this.jar.get(key);\n if (!cookies) {\n return [];\n }\n\n const now = new Date();\n const isSecure = url.protocol === \"https:\";\n const live = cookies.filter((cookie) => {\n if (cookie.expires && cookie.expires <= now) return false;\n return true;\n });\n\n // Write back to evict expired cookies from storage\n if (live.length !== cookies.length) {\n if (live.length === 0) {\n this.jar.delete(key);\n } else {\n this.jar.set(key, live);\n }\n }\n\n return isSecure ? live : live.filter((cookie) => !cookie.secure);\n }\n\n /** Remove all stored cookies. Useful for test isolation. */\n clear() {\n this.jar.clear();\n }\n\n /**\n * Parse a raw `Set-Cookie` header string into a {@link Cookie} object.\n *\n * @param str - Raw `Set-Cookie` header value.\n * @returns Parsed cookie.\n * @throws If the cookie is malformed or contains control characters.\n */\n static parse(str: string): Cookie {\n const parts = str.split(\";\").map((part) => part.trim());\n\n let cookie: Cookie;\n\n if (parts.length > 0) {\n const eqIdx = parts[0].indexOf(\"=\");\n if (eqIdx < 1) {\n throw new Error(\"Invalid cookie\");\n }\n const name = parts[0].slice(0, eqIdx);\n const value = parts[0].slice(eqIdx + 1);\n\n // RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token\n if (!isValidTokenName(name)) {\n throw new Error(\"Invalid cookie: name contains invalid characters\");\n }\n // Reject control characters in value that could enable header injection\n if (hasControlChars(value)) {\n throw new Error(\"Invalid cookie: value contains control characters\");\n }\n\n cookie = {\n name,\n value,\n };\n } else {\n throw new Error(\"Invalid cookie\");\n }\n\n parts.slice(1).forEach((part) => {\n const attrEqIdx = part.indexOf(\"=\");\n const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);\n const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);\n if (!name.trim()) {\n throw new Error(\"Invalid cookie\");\n }\n\n const nameLow = name.toLowerCase();\n // Only strip quotes when both opening and closing characters match\n let val = value;\n if (value && value.length >= 2) {\n const first = value.charAt(0);\n const last = value.charAt(value.length - 1);\n if ((first === '\"' || first === \"'\") && first === last) {\n val = value.slice(1, -1);\n }\n }\n if (nameLow === \"expires\" && val) {\n const date = new Date(val);\n if (!Number.isNaN(date.getTime())) {\n cookie.expires = date;\n }\n }\n if (nameLow === \"samesite\") {\n const normalized = val?.toLowerCase();\n if (normalized === \"lax\") cookie.sameSite = \"Lax\";\n else if (normalized === \"none\") cookie.sameSite = \"None\";\n else if (normalized === \"strict\") cookie.sameSite = \"Strict\";\n }\n if (nameLow === \"secure\") {\n cookie.secure = true;\n }\n if (nameLow === \"httponly\") {\n cookie.httpOnly = true;\n }\n });\n\n return cookie;\n }\n}\n\n/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */\nconst TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\nfunction isValidTokenName(name: string): boolean {\n return TOKEN_RE.test(name);\n}\n\n/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */\nfunction hasControlChars(str: string): boolean {\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n","/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n"],"mappings":"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","names":[]}
// src/index.node.ts
import { Agent } from "undici";
// src/cookieJar.ts
var CookieJar = class _CookieJar {
constructor(jar = /* @__PURE__ */ new Map()) {
this.jar = jar;
}
static MAX_COOKIES_PER_ORIGIN = 50;
/** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */
static MAX_COOKIE_SIZE = 8192;
/**
* Store a `Set-Cookie` header value for the given URL's origin.
*
* @param url - The URL the response was received from.
* @param cookieStr - Raw `Set-Cookie` header string.
*/
setCookie(url, cookieStr) {
if (cookieStr.length > _CookieJar.MAX_COOKIE_SIZE) {
return;
}
let cookie;
try {
cookie = _CookieJar.parse(cookieStr);
} catch {
return;
}
if (cookie.sameSite === "None" && !cookie.secure) {
return;
}
const key = url.origin.toLowerCase();
if (!this.jar.has(key)) {
this.jar.set(key, []);
}
const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];
while (existing.length >= _CookieJar.MAX_COOKIES_PER_ORIGIN) {
existing.shift();
}
this.jar.set(key, [...existing, cookie]);
}
/**
* Return all non-expired cookies for the given URL's origin.
*
* @param url - The URL to match cookies against.
* @returns An array of {@link Cookie} objects (may be empty).
*/
getCookies(url) {
const key = url.origin.toLowerCase();
const cookies = this.jar.get(key);
if (!cookies) {
return [];
}
const now = /* @__PURE__ */ new Date();
const isSecure = url.protocol === "https:";
const live = cookies.filter((cookie) => {
if (cookie.expires && cookie.expires <= now) return false;
return true;
});
if (live.length !== cookies.length) {
if (live.length === 0) {
this.jar.delete(key);
} else {
this.jar.set(key, live);
}
}
return isSecure ? live : live.filter((cookie) => !cookie.secure);
}
/** Remove all stored cookies. Useful for test isolation. */
clear() {
this.jar.clear();
}
/**
* Parse a raw `Set-Cookie` header string into a {@link Cookie} object.
*
* @param str - Raw `Set-Cookie` header value.
* @returns Parsed cookie.
* @throws If the cookie is malformed or contains control characters.
*/
static parse(str) {
const parts = str.split(";").map((part) => part.trim());
let cookie;
if (parts.length > 0) {
const eqIdx = parts[0].indexOf("=");
if (eqIdx < 1) {
throw new Error("Invalid cookie");
}
const name = parts[0].slice(0, eqIdx);
const value = parts[0].slice(eqIdx + 1);
if (!isValidTokenName(name)) {
throw new Error("Invalid cookie: name contains invalid characters");
}
if (hasControlChars(value)) {
throw new Error("Invalid cookie: value contains control characters");
}
cookie = {
name,
value
};
} else {
throw new Error("Invalid cookie");
}
parts.slice(1).forEach((part) => {
const attrEqIdx = part.indexOf("=");
const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);
const value = attrEqIdx === -1 ? void 0 : part.slice(attrEqIdx + 1);
if (!name.trim()) {
throw new Error("Invalid cookie");
}
const nameLow = name.toLowerCase();
let val = value;
if (value && value.length >= 2) {
const first = value.charAt(0);
const last = value.charAt(value.length - 1);
if ((first === '"' || first === "'") && first === last) {
val = value.slice(1, -1);
}
}
if (nameLow === "expires" && val) {
const date = new Date(val);
if (!Number.isNaN(date.getTime())) {
cookie.expires = date;
}
}
if (nameLow === "samesite") {
const normalized = val?.toLowerCase();
if (normalized === "lax") cookie.sameSite = "Lax";
else if (normalized === "none") cookie.sameSite = "None";
else if (normalized === "strict") cookie.sameSite = "Strict";
}
if (nameLow === "secure") {
cookie.secure = true;
}
if (nameLow === "httponly") {
cookie.httpOnly = true;
}
});
return cookie;
}
};
var TOKEN_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
function isValidTokenName(name) {
return TOKEN_RE.test(name);
}
function hasControlChars(str) {
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (code <= 31 || code === 127) return true;
}
return false;
}
// src/shared.ts
function buildUrl(base, params) {
const url = new URL(base);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== void 0) {
url.searchParams.append(key, String(value));
}
}
}
return url;
}
function serializeBody(body) {
if (body == null) return void 0;
if (body instanceof Uint8Array) {
return body;
}
return JSON.stringify(body);
}
function applyJsonContentType(body, headers) {
if (body != null && !(body instanceof Uint8Array) && !headers.has("content-type")) {
headers.set("content-type", "application/json");
}
}
async function parseJsonSafely(res) {
if (res.status === 204 || res.status === 205) {
return null;
}
const text = await res.text();
if (text.length === 0) {
return null;
}
try {
return JSON.parse(text);
} catch {
return text;
}
}
function applyCookiesToHeaders(headers, url, jar) {
const cookies = jar.getCookies(url);
if (cookies.length > 0) {
const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join("; ");
const existing = headers.get("cookie");
headers.set("cookie", existing ? `${existing}; ${jarCookies}` : jarCookies);
}
}
function storeResponseCookies(url, headers, jar) {
if (typeof headers.getSetCookie !== "function") return;
for (const cookie of headers.getSetCookie()) {
jar.setCookie(url, cookie);
}
}
function headersToRecord(headers) {
const result = {};
headers.forEach((value, key) => {
result[key] = value;
});
if (typeof headers.getSetCookie === "function") {
const cookies = headers.getSetCookie();
if (cookies.length > 0) {
result["set-cookie"] = cookies;
}
}
return result;
}
// src/index.node.ts
var defaultCookieJar = new CookieJar();
var dispatcherCache = /* @__PURE__ */ new Map();
var MAX_DISPATCHERS = 50;
async function aptosClient(requestOptions) {
return jsonRequest(requestOptions);
}
async function jsonRequest(requestOptions) {
return await doRequest(requestOptions, "json");
}
async function bcsRequest(requestOptions) {
return await doRequest(requestOptions, "arrayBuffer");
}
async function doRequest(requestOptions, mode) {
const { url, method, params, headers, body, http2 = true } = requestOptions;
const jar = requestOptions.cookieJar ?? defaultCookieJar;
if (method !== "GET" && method !== "POST") {
throw new Error(`Unsupported method: ${method}`);
}
const requestUrl = buildUrl(url, params);
const requestHeaders = buildHeaders(requestUrl, headers, jar);
const dispatcher = getDispatcher(requestUrl.origin, http2);
const init = {
method,
headers: requestHeaders,
dispatcher
};
const serialized = serializeBody(body);
if (serialized !== void 0) {
init.body = serialized;
applyJsonContentType(body, requestHeaders);
}
const res = await fetch(requestUrl, init);
storeResponseCookies(requestUrl, res.headers, jar);
const data = mode === "json" ? await parseJsonSafely(res) : await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
config: { ...init, headers: headersToRecord(requestHeaders) },
request: {
url: requestUrl.toString(),
method
},
response: res,
headers: headersToRecord(res.headers)
};
}
function getDispatcher(origin, http2) {
const key = `${origin}|h2=${http2}`;
const cached = dispatcherCache.get(key);
if (cached) {
dispatcherCache.delete(key);
dispatcherCache.set(key, cached);
return cached;
}
if (dispatcherCache.size >= MAX_DISPATCHERS) {
const oldest = dispatcherCache.keys().next().value;
dispatcherCache.get(oldest).destroy().catch(() => {
});
dispatcherCache.delete(oldest);
}
const agent = new Agent({
allowH2: http2
});
dispatcherCache.set(key, agent);
return agent;
}
function buildHeaders(url, headers, jar) {
const result = new Headers();
for (const [key, value] of Object.entries(headers ?? {})) {
if (value !== void 0) {
result.set(key, String(value));
}
}
applyCookiesToHeaders(result, url, jar);
return result;
}
export {
CookieJar,
bcsRequest,
aptosClient as default,
jsonRequest
};
//# sourceMappingURL=index.node.mjs.map
{"version":3,"sources":["../../src/index.node.ts","../../src/cookieJar.ts","../../src/shared.ts"],"sourcesContent":["/**\n * Node.js HTTP client backed by {@link https://undici.nodejs.org | undici}.\n *\n * @remarks\n * This entry point is selected when the package is imported from Node.js\n * (via the `\"node\"` export condition). It uses undici's `Agent` with\n * configurable HTTP/2 support (`allowH2`). Agents are cached per origin\n * so connections are reused across requests to the same host.\n *\n * @module index.node\n */\nimport { Agent } from \"undici\";\nimport { CookieJar } from \"./cookieJar\";\nimport {\n applyCookiesToHeaders,\n applyJsonContentType,\n buildUrl,\n headersToRecord,\n parseJsonSafely,\n serializeBody,\n storeResponseCookies,\n} from \"./shared\";\nimport type { AptosClientRequest, AptosClientResponse, CookieJarLike } from \"./types\";\n\nexport { CookieJar } from \"./cookieJar\";\nexport type { CookieJarLike } from \"./types\";\n\nconst defaultCookieJar = new CookieJar();\n\n/** One dispatcher per origin + HTTP/2 mode for connection reuse. */\nconst dispatcherCache = new Map<string, Agent>();\nconst MAX_DISPATCHERS = 50;\n\n/**\n * Send a JSON request to an Aptos API endpoint.\n *\n * This is the default export and the primary entry point for most callers.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param requestOptions - Request configuration.\n * @returns Parsed response with status, headers, and deserialized body.\n *\n * @example\n * ```ts\n * import aptosClient from \"@aptos-labs/aptos-client\";\n *\n * const { data } = await aptosClient<{ chain_id: number }>({\n * url: \"https://fullnode.mainnet.aptoslabs.com/v1\",\n * method: \"GET\",\n * });\n * ```\n */\nexport default async function aptosClient<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return jsonRequest(requestOptions);\n}\n\n/**\n * Send a request and parse the response as JSON.\n *\n * Identical to the default export; useful when a named import is preferred.\n *\n * @typeParam Res - Expected shape of the JSON response body.\n * @param requestOptions - Request configuration.\n */\nexport async function jsonRequest<Res>(requestOptions: AptosClientRequest): Promise<AptosClientResponse<Res>> {\n return await doRequest(requestOptions, \"json\");\n}\n\n/**\n * Send a request and return the response as an `ArrayBuffer`.\n *\n * Intended for BCS-encoded responses from the Aptos API.\n *\n * @experimental\n * @param requestOptions - Request configuration.\n */\nexport async function bcsRequest(requestOptions: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {\n return await doRequest(requestOptions, \"arrayBuffer\");\n}\n\n/** @internal */\ntype ResponseMode = \"json\" | \"arrayBuffer\";\n\n/**\n * Core request handler shared by {@link jsonRequest} and {@link bcsRequest}.\n * @internal\n */\nasync function doRequest<Res>(\n requestOptions: AptosClientRequest,\n mode: ResponseMode,\n): Promise<AptosClientResponse<Res>> {\n const { url, method, params, headers, body, http2 = true } = requestOptions;\n const jar = requestOptions.cookieJar ?? defaultCookieJar;\n\n if (method !== \"GET\" && method !== \"POST\") {\n throw new Error(`Unsupported method: ${method}`);\n }\n\n const requestUrl = buildUrl(url, params);\n const requestHeaders = buildHeaders(requestUrl, headers, jar);\n const dispatcher = getDispatcher(requestUrl.origin, http2);\n\n const init: RequestInit & { dispatcher?: Agent } = {\n method,\n headers: requestHeaders,\n dispatcher,\n };\n\n const serialized = serializeBody(body);\n if (serialized !== undefined) {\n init.body = serialized;\n applyJsonContentType(body, requestHeaders);\n }\n\n const res = await fetch(requestUrl, init);\n\n storeResponseCookies(requestUrl, res.headers, jar);\n\n const data = mode === \"json\" ? await parseJsonSafely(res) : await res.arrayBuffer();\n\n return {\n status: res.status,\n statusText: res.statusText,\n data,\n config: { ...init, headers: headersToRecord(requestHeaders) },\n request: {\n url: requestUrl.toString(),\n method,\n },\n response: res,\n headers: headersToRecord(res.headers),\n };\n}\n\n/**\n * Return a cached undici `Agent` for the given origin, creating one if needed.\n *\n * @param origin - URL origin (scheme + host + port).\n * @param http2 - Whether to enable HTTP/2 via ALPN (`allowH2`).\n * @internal\n */\nfunction getDispatcher(origin: string, http2: boolean): Agent {\n const key = `${origin}|h2=${http2}`;\n const cached = dispatcherCache.get(key);\n if (cached) {\n // Move to end of Map (most-recently-used)\n dispatcherCache.delete(key);\n dispatcherCache.set(key, cached);\n return cached;\n }\n\n // Evict oldest entry if cache is full\n if (dispatcherCache.size >= MAX_DISPATCHERS) {\n // biome-ignore lint/style/noNonNullAssertion: cache size check guarantees entry exists\n const oldest = dispatcherCache.keys().next().value!;\n // biome-ignore lint/style/noNonNullAssertion: oldest key was just retrieved from cache\n dispatcherCache\n .get(oldest)!\n .destroy()\n .catch(() => {});\n dispatcherCache.delete(oldest);\n }\n\n const agent = new Agent({\n allowH2: http2,\n });\n\n dispatcherCache.set(key, agent);\n return agent;\n}\n\n/**\n * Merge caller-supplied headers with cookies from the jar.\n * @internal\n */\nfunction buildHeaders(url: URL, headers: AptosClientRequest[\"headers\"] | undefined, jar: CookieJarLike): Headers {\n const result = new Headers();\n\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (value !== undefined) {\n result.set(key, String(value));\n }\n }\n\n applyCookiesToHeaders(result, url, jar);\n\n return result;\n}\n","/** A parsed cookie with optional attributes. */\ninterface Cookie {\n name: string;\n value: string;\n expires?: Date;\n sameSite?: \"Lax\" | \"None\" | \"Strict\";\n secure?: boolean;\n httpOnly?: boolean;\n}\n\n/**\n * Minimal, origin-scoped cookie jar used by the Node and fetch entry points.\n *\n * @remarks\n * Cookies are keyed by origin (scheme + host + port). Expired cookies are\n * filtered out lazily when {@link getCookies} is called. The browser entry\n * point delegates cookie handling to the browser engine and does not use\n * this class.\n *\n * **Note:** A single module-level `CookieJar` instance is shared across all\n * requests in the same process. In multi-tenant server-side environments,\n * create a separate instance and pass it via {@link AptosClientRequest.cookieJar}\n * to avoid cross-request cookie leakage.\n */\nexport class CookieJar {\n static readonly MAX_COOKIES_PER_ORIGIN = 50;\n /** RFC 6265 §6.1 recommends at least 4096 bytes per cookie. */\n static readonly MAX_COOKIE_SIZE = 8192;\n\n constructor(private jar = new Map<string, Cookie[]>()) {}\n\n /**\n * Store a `Set-Cookie` header value for the given URL's origin.\n *\n * @param url - The URL the response was received from.\n * @param cookieStr - Raw `Set-Cookie` header string.\n */\n setCookie(url: URL, cookieStr: string) {\n if (cookieStr.length > CookieJar.MAX_COOKIE_SIZE) {\n return; // Silently drop oversized cookies\n }\n\n let cookie: Cookie;\n try {\n cookie = CookieJar.parse(cookieStr);\n } catch {\n return; // Silently skip malformed cookies, matching browser behavior\n }\n\n // RFC 6265bis: SameSite=None requires the Secure attribute\n if (cookie.sameSite === \"None\" && !cookie.secure) {\n return;\n }\n\n const key = url.origin.toLowerCase();\n if (!this.jar.has(key)) {\n this.jar.set(key, []);\n }\n\n const existing = this.jar.get(key)?.filter((c) => c.name !== cookie.name) || [];\n // Evict oldest cookies if we're at the per-origin cap\n while (existing.length >= CookieJar.MAX_COOKIES_PER_ORIGIN) {\n existing.shift();\n }\n this.jar.set(key, [...existing, cookie]);\n }\n\n /**\n * Return all non-expired cookies for the given URL's origin.\n *\n * @param url - The URL to match cookies against.\n * @returns An array of {@link Cookie} objects (may be empty).\n */\n getCookies(url: URL): Cookie[] {\n const key = url.origin.toLowerCase();\n const cookies = this.jar.get(key);\n if (!cookies) {\n return [];\n }\n\n const now = new Date();\n const isSecure = url.protocol === \"https:\";\n const live = cookies.filter((cookie) => {\n if (cookie.expires && cookie.expires <= now) return false;\n return true;\n });\n\n // Write back to evict expired cookies from storage\n if (live.length !== cookies.length) {\n if (live.length === 0) {\n this.jar.delete(key);\n } else {\n this.jar.set(key, live);\n }\n }\n\n return isSecure ? live : live.filter((cookie) => !cookie.secure);\n }\n\n /** Remove all stored cookies. Useful for test isolation. */\n clear() {\n this.jar.clear();\n }\n\n /**\n * Parse a raw `Set-Cookie` header string into a {@link Cookie} object.\n *\n * @param str - Raw `Set-Cookie` header value.\n * @returns Parsed cookie.\n * @throws If the cookie is malformed or contains control characters.\n */\n static parse(str: string): Cookie {\n const parts = str.split(\";\").map((part) => part.trim());\n\n let cookie: Cookie;\n\n if (parts.length > 0) {\n const eqIdx = parts[0].indexOf(\"=\");\n if (eqIdx < 1) {\n throw new Error(\"Invalid cookie\");\n }\n const name = parts[0].slice(0, eqIdx);\n const value = parts[0].slice(eqIdx + 1);\n\n // RFC 6265 §4.1.1: cookie-name must be a valid RFC 7230 token\n if (!isValidTokenName(name)) {\n throw new Error(\"Invalid cookie: name contains invalid characters\");\n }\n // Reject control characters in value that could enable header injection\n if (hasControlChars(value)) {\n throw new Error(\"Invalid cookie: value contains control characters\");\n }\n\n cookie = {\n name,\n value,\n };\n } else {\n throw new Error(\"Invalid cookie\");\n }\n\n parts.slice(1).forEach((part) => {\n const attrEqIdx = part.indexOf(\"=\");\n const name = attrEqIdx === -1 ? part : part.slice(0, attrEqIdx);\n const value = attrEqIdx === -1 ? undefined : part.slice(attrEqIdx + 1);\n if (!name.trim()) {\n throw new Error(\"Invalid cookie\");\n }\n\n const nameLow = name.toLowerCase();\n // Only strip quotes when both opening and closing characters match\n let val = value;\n if (value && value.length >= 2) {\n const first = value.charAt(0);\n const last = value.charAt(value.length - 1);\n if ((first === '\"' || first === \"'\") && first === last) {\n val = value.slice(1, -1);\n }\n }\n if (nameLow === \"expires\" && val) {\n const date = new Date(val);\n if (!Number.isNaN(date.getTime())) {\n cookie.expires = date;\n }\n }\n if (nameLow === \"samesite\") {\n const normalized = val?.toLowerCase();\n if (normalized === \"lax\") cookie.sameSite = \"Lax\";\n else if (normalized === \"none\") cookie.sameSite = \"None\";\n else if (normalized === \"strict\") cookie.sameSite = \"Strict\";\n }\n if (nameLow === \"secure\") {\n cookie.secure = true;\n }\n if (nameLow === \"httponly\") {\n cookie.httpOnly = true;\n }\n });\n\n return cookie;\n }\n}\n\n/** RFC 7230 token — rejects CTL, space, and separator characters. @internal */\nconst TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\nfunction isValidTokenName(name: string): boolean {\n return TOKEN_RE.test(name);\n}\n\n/** Check if a string contains CTL characters per RFC 6265 (0x00-0x1F and 0x7F). @internal */\nfunction hasControlChars(str: string): boolean {\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code <= 0x1f || code === 0x7f) return true;\n }\n return false;\n}\n","/**\n * Shared utilities used by all entry points (Node, fetch, browser).\n *\n * @remarks\n * Extracted to a single module so that parsing, serialization, URL building,\n * and cookie logic stay consistent across runtimes.\n *\n * @internal\n * @module shared\n */\nimport type { AptosClientRequest, CookieJarLike } from \"./types\";\n\n/**\n * Build a `URL` from a base string and optional query parameters.\n * `bigint` values are stringified automatically via `String()`.\n * @internal\n */\nexport function buildUrl(base: string, params?: AptosClientRequest[\"params\"]): URL {\n const url = new URL(base);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n // String(value) correctly handles bigint: String(12345n) === \"12345\"\n url.searchParams.append(key, String(value));\n }\n }\n }\n return url;\n}\n\n/**\n * Serialize a request body to a `BodyInit`-compatible value.\n *\n * - `null` / `undefined` → `undefined` (no body sent)\n * - `Uint8Array` → passed through (valid `ArrayBufferView`/`BodyInit`)\n * - Anything else → `JSON.stringify`\n *\n * @internal\n */\nexport function serializeBody(body: unknown): BodyInit | undefined {\n if (body == null) return undefined;\n if (body instanceof Uint8Array) {\n // Uint8Array is a valid BodyInit at runtime (ArrayBufferView), cast for TS compatibility\n return body as unknown as BodyInit;\n }\n return JSON.stringify(body);\n}\n\n/**\n * Set the `content-type` header to `application/json` when the body is\n * a non-binary, non-null value and no content-type has been set already.\n * @internal\n */\nexport function applyJsonContentType(body: unknown, headers: Headers): void {\n if (body != null && !(body instanceof Uint8Array) && !headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n}\n\n/**\n * Parse a response body as JSON, returning the raw text when parsing fails.\n *\n * Returning raw text (instead of throwing) preserves backward compatibility\n * with v2, where `got` returned error responses as normal `AptosClientResponse`\n * objects. This lets the caller (e.g. the TS SDK) inspect the status code and\n * handle the error however it chooses.\n *\n * @internal\n */\n// biome-ignore lint/suspicious/noExplicitAny: JSON.parse returns unknown shape; caller provides Res generic\nexport async function parseJsonSafely(res: Response): Promise<any> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/**\n * Merge cookies from a {@link CookieJarLike} into the request headers.\n * @internal\n */\nexport function applyCookiesToHeaders(headers: Headers, url: URL, jar: CookieJarLike): void {\n const cookies = jar.getCookies(url);\n if (cookies.length > 0) {\n const jarCookies = cookies.map((c) => `${c.name}=${c.value}`).join(\"; \");\n const existing = headers.get(\"cookie\");\n headers.set(\"cookie\", existing ? `${existing}; ${jarCookies}` : jarCookies);\n }\n}\n\n/**\n * Store any `Set-Cookie` headers from the response in the cookie jar.\n *\n * Includes a defensive check for `Headers.getSetCookie()` availability,\n * since it may be absent in some React Native environments.\n * @internal\n */\nexport function storeResponseCookies(url: URL, headers: Headers, jar: CookieJarLike): void {\n if (typeof headers.getSetCookie !== \"function\") return;\n for (const cookie of headers.getSetCookie()) {\n jar.setCookie(url, cookie);\n }\n}\n\n/**\n * Convert a `Headers` instance to a plain `Record<string, string | string[]>`.\n *\n * This preserves backward compatibility with aptos-client v2, which\n * returned Node's `IncomingHttpHeaders` (a plain object) from the `got`\n * library. Consumers (e.g. the TS SDK) access headers via bracket\n * notation (`response.headers[\"x-aptos-cursor\"]`), which only works on\n * plain objects — not on `Headers` instances.\n *\n * Multi-value `set-cookie` headers are returned as `string[]` to match\n * Node's `IncomingHttpHeaders` shape and avoid losing cookie boundaries.\n *\n * @internal\n */\nexport function headersToRecord(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, key) => {\n result[key] = value;\n });\n if (typeof headers.getSetCookie === \"function\") {\n const cookies = headers.getSetCookie();\n if (cookies.length > 0) {\n result[\"set-cookie\"] = cookies;\n }\n }\n return result;\n}\n"],"mappings":"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","names":[]}