@aptos-labs/aptos-client
Advanced tools
| /** 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":"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"} |
| /** | ||
| * 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"} |
+125
| /** | ||
| * 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":""} |
+197
| /** 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; | ||
| } |
+139
| /** | ||
| * 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; | ||
| } |
+93
| /** | ||
| * 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" | ||
| } |
+3
-7
@@ -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":";AAwBO,IAAM,YAAN,MAAM,WAAU;AAAA,EAKrB,YAAoB,MAAM,oBAAI,IAAsB,GAAG;AAAnC;AAAA,EAAoC;AAAA,EAJxD,OAAgB,yBAAyB;AAAA;AAAA,EAEzC,OAAgB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlC,UAAU,KAAU,WAAmB;AACrC,QAAI,UAAU,SAAS,WAAU,iBAAiB;AAChD;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,WAAU,MAAM,SAAS;AAAA,IACpC,QAAQ;AACN;AAAA,IACF;AAGA,QAAI,OAAO,aAAa,UAAU,CAAC,OAAO,QAAQ;AAChD;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,QAAI,CAAC,KAAK,IAAI,IAAI,GAAG,GAAG;AACtB,WAAK,IAAI,IAAI,KAAK,CAAC,CAAC;AAAA,IACtB;AAEA,UAAM,WAAW,KAAK,IAAI,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,IAAI,KAAK,CAAC;AAE9E,WAAO,SAAS,UAAU,WAAU,wBAAwB;AAC1D,eAAS,MAAM;AAAA,IACjB;AACA,SAAK,IAAI,IAAI,KAAK,CAAC,GAAG,UAAU,MAAM,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,KAAoB;AAC7B,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,UAAM,UAAU,KAAK,IAAI,IAAI,GAAG;AAChC,QAAI,CAAC,SAAS;AACZ,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,WAAW,IAAI,aAAa;AAClC,UAAM,OAAO,QAAQ,OAAO,CAAC,WAAW;AACtC,UAAI,OAAO,WAAW,OAAO,WAAW,IAAK,QAAO;AACpD,aAAO;AAAA,IACT,CAAC;AAGD,QAAI,KAAK,WAAW,QAAQ,QAAQ;AAClC,UAAI,KAAK,WAAW,GAAG;AACrB,aAAK,IAAI,OAAO,GAAG;AAAA,MACrB,OAAO;AACL,aAAK,IAAI,IAAI,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,WAAO,WAAW,OAAO,KAAK,OAAO,CAAC,WAAW,CAAC,OAAO,MAAM;AAAA,EACjE;AAAA;AAAA,EAGA,QAAQ;AACN,SAAK,IAAI,MAAM;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,MAAM,KAAqB;AAChC,UAAM,QAAQ,IAAI,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAEtD,QAAI;AAEJ,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,GAAG;AAClC,UAAI,QAAQ,GAAG;AACb,cAAM,IAAI,MAAM,gBAAgB;AAAA,MAClC;AACA,YAAM,OAAO,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK;AACpC,YAAM,QAAQ,MAAM,CAAC,EAAE,MAAM,QAAQ,CAAC;AAGtC,UAAI,CAAC,iBAAiB,IAAI,GAAG;AAC3B,cAAM,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAEA,UAAI,gBAAgB,KAAK,GAAG;AAC1B,cAAM,IAAI,MAAM,mDAAmD;AAAA,MACrE;AAEA,eAAS;AAAA,QACP;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,gBAAgB;AAAA,IAClC;AAEA,UAAM,MAAM,CAAC,EAAE,QAAQ,CAAC,SAAS;AAC/B,YAAM,YAAY,KAAK,QAAQ,GAAG;AAClC,YAAM,OAAO,cAAc,KAAK,OAAO,KAAK,MAAM,GAAG,SAAS;AAC9D,YAAM,QAAQ,cAAc,KAAK,SAAY,KAAK,MAAM,YAAY,CAAC;AACrE,UAAI,CAAC,KAAK,KAAK,GAAG;AAChB,cAAM,IAAI,MAAM,gBAAgB;AAAA,MAClC;AAEA,YAAM,UAAU,KAAK,YAAY;AAEjC,UAAI,MAAM;AACV,UAAI,SAAS,MAAM,UAAU,GAAG;AAC9B,cAAM,QAAQ,MAAM,OAAO,CAAC;AAC5B,cAAM,OAAO,MAAM,OAAO,MAAM,SAAS,CAAC;AAC1C,aAAK,UAAU,OAAO,UAAU,QAAQ,UAAU,MAAM;AACtD,gBAAM,MAAM,MAAM,GAAG,EAAE;AAAA,QACzB;AAAA,MACF;AACA,UAAI,YAAY,aAAa,KAAK;AAChC,cAAM,OAAO,IAAI,KAAK,GAAG;AACzB,YAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AACjC,iBAAO,UAAU;AAAA,QACnB;AAAA,MACF;AACA,UAAI,YAAY,YAAY;AAC1B,cAAM,aAAa,KAAK,YAAY;AACpC,YAAI,eAAe,MAAO,QAAO,WAAW;AAAA,iBACnC,eAAe,OAAQ,QAAO,WAAW;AAAA,iBACzC,eAAe,SAAU,QAAO,WAAW;AAAA,MACtD;AACA,UAAI,YAAY,UAAU;AACxB,eAAO,SAAS;AAAA,MAClB;AACA,UAAI,YAAY,YAAY;AAC1B,eAAO,WAAW;AAAA,MACpB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;AAGA,IAAM,WAAW;AACjB,SAAS,iBAAiB,MAAuB;AAC/C,SAAO,SAAS,KAAK,IAAI;AAC3B;AAGA,SAAS,gBAAgB,KAAsB;AAC7C,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,QAAI,QAAQ,MAAQ,SAAS,IAAM,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;;;ACnLO,SAAS,SAAS,MAAc,QAA4C;AACjF,QAAM,MAAM,IAAI,IAAI,IAAI;AACxB,MAAI,QAAQ;AACV,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,UAAU,QAAW;AAEvB,YAAI,aAAa,OAAO,KAAK,OAAO,KAAK,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,cAAc,MAAqC;AACjE,MAAI,QAAQ,KAAM,QAAO;AACzB,MAAI,gBAAgB,YAAY;AAE9B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,UAAU,IAAI;AAC5B;AAOO,SAAS,qBAAqB,MAAe,SAAwB;AAC1E,MAAI,QAAQ,QAAQ,EAAE,gBAAgB,eAAe,CAAC,QAAQ,IAAI,cAAc,GAAG;AACjF,YAAQ,IAAI,gBAAgB,kBAAkB;AAAA,EAChD;AACF;AAaA,eAAsB,gBAAgB,KAA6B;AACjE,MAAI,IAAI,WAAW,OAAO,IAAI,WAAW,KAAK;AAC5C,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,sBAAsB,SAAkB,KAAU,KAA0B;AAC1F,QAAM,UAAU,IAAI,WAAW,GAAG;AAClC,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,aAAa,QAAQ,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,KAAK,EAAE,EAAE,KAAK,IAAI;AACvE,UAAM,WAAW,QAAQ,IAAI,QAAQ;AACrC,YAAQ,IAAI,UAAU,WAAW,GAAG,QAAQ,KAAK,UAAU,KAAK,UAAU;AAAA,EAC5E;AACF;AASO,SAAS,qBAAqB,KAAU,SAAkB,KAA0B;AACzF,MAAI,OAAO,QAAQ,iBAAiB,WAAY;AAChD,aAAW,UAAU,QAAQ,aAAa,GAAG;AAC3C,QAAI,UAAU,KAAK,MAAM;AAAA,EAC3B;AACF;AAgBO,SAAS,gBAAgB,SAAqD;AACnF,QAAM,SAA4C,CAAC;AACnD,UAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,WAAO,GAAG,IAAI;AAAA,EAChB,CAAC;AACD,MAAI,OAAO,QAAQ,iBAAiB,YAAY;AAC9C,UAAM,UAAU,QAAQ,aAAa;AACrC,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO,YAAY,IAAI;AAAA,IACzB;AAAA,EACF;AACA,SAAO;AACT;;;AChHA,IAAM,mBAAmB,IAAI,UAAU;AAEvC,IAAI,cAAc;AAqBlB,eAAO,YAAwC,SAAgE;AAC7G,SAAO,YAAiB,OAAO;AACjC;AAUA,eAAsB,YAAiB,SAAgE;AACrG,QAAM,EAAE,YAAY,eAAe,IAAI,IAAI,aAAa,OAAO;AAE/D,QAAM,MAAM,MAAM,MAAM,YAAY,aAAa;AACjD,uBAAqB,IAAI,IAAI,UAAU,GAAG,IAAI,SAAS,GAAG;AAC1D,QAAM,OAAO,MAAM,gBAAgB,GAAG;AAEtC,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,YAAY,IAAI;AAAA,IAChB;AAAA,IACA,SAAS,gBAAgB,IAAI,OAAO;AAAA,IACpC,QAAQ;AAAA,EACV;AACF;AAUA,eAAsB,WAAW,SAAwE;AACvG,QAAM,EAAE,YAAY,eAAe,IAAI,IAAI,aAAa,OAAO;AAE/D,QAAM,MAAM,MAAM,MAAM,YAAY,aAAa;AACjD,uBAAqB,IAAI,IAAI,UAAU,GAAG,IAAI,SAAS,GAAG;AAC1D,QAAM,OAAO,MAAM,IAAI,YAAY;AAEnC,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,YAAY,IAAI;AAAA,IAChB;AAAA,IACA,SAAS,gBAAgB,IAAI,OAAO;AAAA,IACpC,QAAQ;AAAA,EACV;AACF;AAGA,SAAS,aAAa,SAA6B;AACjD,MAAI,QAAQ,WAAW,SAAS,QAAQ,WAAW,QAAQ;AACzD,UAAM,IAAI,MAAM,uBAAuB,QAAQ,MAAM,EAAE;AAAA,EACzD;AAEA,MAAI,CAAC,eAAe,QAAQ,UAAU,QAAW;AAC/C,kBAAc;AACd,YAAQ,KAAK,kGAAkG;AAAA,EACjH;AAEA,QAAM,MAAM,QAAQ,aAAa;AAEjC,QAAM,UAAU,IAAI,QAAQ;AAC5B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,WAAW,CAAC,CAAC,GAAG;AACjE,QAAI,UAAU,QAAW;AACvB,cAAQ,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,aAAa,SAAS,QAAQ,KAAK,QAAQ,MAAM;AAEvD,wBAAsB,SAAS,YAAY,GAAG;AAE9C,QAAM,OAAO,cAAc,QAAQ,IAAI;AACvC,MAAI,SAAS,QAAW;AACtB,yBAAqB,QAAQ,MAAM,OAAO;AAAA,EAC5C;AAEA,QAAM,gBAA6B;AAAA,IACjC,QAAQ,QAAQ;AAAA,IAChB,SAAS,gBAAgB,OAAO;AAAA,IAChC;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,WAAW,SAAS,GAAG,eAAe,IAAI;AACjE;","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":[]} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
5
-44.44%33
57.14%Yes
NaN103981
-50.61%1774
-9.07%134
-2.9%11
10%+ Added