{"version":3,"file":"client.cjs","names":["isAnubisChallenge","passChallenge"],"sources":["../../src/anubis/client.ts"],"sourcesContent":["import {\n  type ChallengeResult,\n  type FetchLike,\n  isAnubisChallenge,\n  passChallenge\n} from './challenge';\n\nexport interface AnubisClientOptions {\n  /** Defaults to the global `fetch`. */\n  fetch?: FetchLike;\n  /** Give up on a proof-of-work after this long. Defaults to 10 seconds. */\n  timeBudgetMs?: number;\n}\n\nexport interface AnubisClient {\n  /** Whether a response body is an Anubis interstitial rather than content. */\n  isChallenge(html: string): boolean;\n  /**\n   * Solve the given interstitial and cache the resulting cookie. Resolves\n   * `true` when the request is worth retrying. Concurrent calls share a single\n   * proof-of-work, since the cookie they produce is shared anyway.\n   */\n  pass(html: string, headers: Headers, url: string, requestHeaders?: Headers): Promise<boolean>;\n  /** The cached cookie, e.g. to persist between runs. */\n  getCookie(): string | null;\n  /** Seed the cache from a previous run or a per-tenant store. */\n  setCookie(cookie: string | null): void;\n  /** Forget the cookie so the next challenge is solved from scratch. */\n  reset(): void;\n  /** Whether cookies must be left to the runtime rather than sent by hand. */\n  usesPlatformCookieJar(): boolean;\n}\n\n/**\n * An Anubis-aware cookie holder. Each client keeps its own cookie, so callers\n * with separate egress IPs (Anubis binds the cookie to one) can hold one each.\n */\nexport const createAnubisClient = (options: AnubisClientOptions = {}): AnubisClient => {\n  const doFetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n  const timeBudgetMs = options.timeBudgetMs;\n\n  let cookie: string | null = null;\n  let platformCookieJar = false;\n  let pending: Promise<ChallengeResult | null> | null = null;\n\n  return {\n    isChallenge: isAnubisChallenge,\n    getCookie: () => cookie,\n    setCookie: (value) => {\n      cookie = value;\n    },\n    reset: () => {\n      cookie = null;\n      pending = null;\n    },\n    usesPlatformCookieJar: () => platformCookieJar,\n\n    pass: async (html, headers, url, requestHeaders) => {\n      if (!pending) {\n        pending = passChallenge({\n          html,\n          headers,\n          url,\n          requestHeaders,\n          fetch: doFetch,\n          timeBudgetMs\n        }).finally(() => {\n          pending = null;\n        });\n      }\n\n      const result = await pending;\n      if (!result) {\n        return false;\n      }\n      cookie = result.cookie;\n      platformCookieJar = result.platformCookieJar;\n      return true;\n    }\n  };\n};\n"],"mappings":";;;;;;AAqCA,MAAa,sBAAsB,UAA+B,CAAC,MAAoB;CACrF,MAAM,UAAU,QAAQ,WAAW,OAAO,SAAS,WAAW,MAAM,OAAO,IAAI;CAC/E,MAAM,eAAe,QAAQ;CAE7B,IAAI,SAAwB;CAC5B,IAAI,oBAAoB;CACxB,IAAI,UAAkD;CAEtD,OAAO;EACL,aAAaA,kBAAAA;EACb,iBAAiB;EACjB,YAAY,UAAU;GACpB,SAAS;EACX;EACA,aAAa;GACX,SAAS;GACT,UAAU;EACZ;EACA,6BAA6B;EAE7B,MAAM,OAAO,MAAM,SAAS,KAAK,mBAAmB;GAClD,IAAI,CAAC,SACH,UAAUC,kBAAAA,cAAc;IACtB;IACA;IACA;IACA;IACA,OAAO;IACP;GACF,CAAC,CAAC,CAAC,cAAc;IACf,UAAU;GACZ,CAAC;GAGH,MAAM,SAAS,MAAM;GACrB,IAAI,CAAC,QACH,OAAO;GAET,SAAS,OAAO;GAChB,oBAAoB,OAAO;GAC3B,OAAO;EACT;CACF;AACF"}