From 25fe9d739adc373a5da034f612d87c0ea68a5826 Mon Sep 17 00:00:00 2001 From: germondai Date: Wed, 8 Jul 2026 20:06:24 +0200 Subject: [PATCH] feat(types): centralize BrowserHandle, BrowserFingerprint, SupportedMethod --- packages/browser/src/fingerprint.ts | 9 +++----- packages/browser/src/pool.ts | 15 ++++-------- packages/types/src/index.ts | 36 +++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/packages/browser/src/fingerprint.ts b/packages/browser/src/fingerprint.ts index 0b2d063..264a301 100644 --- a/packages/browser/src/fingerprint.ts +++ b/packages/browser/src/fingerprint.ts @@ -1,3 +1,5 @@ +import type { BrowserFingerprint } from "@trawl/types" + // The HTTP-level fingerprint sent with every request. Must match the actual browser // engine (Camoufox = Firefox) or anti-bot services do UA-vs-engine cross-checks and // flag the mismatch. Per-request the orchestrator picks one of these UAs at random @@ -15,12 +17,7 @@ export const FINGERPRINT = { // Picked from by the pool per browser-instance so HTTP headers + browser // fingerprint (OS, navigator.platform) stay consistent. -export const FINGERPRINT_POOL: ReadonlyArray<{ - userAgent: string - platform: "Win32" | "MacIntel" | "Linux x86_64" | "Linux armv8" - locale: string - timezone: string -}> = [ +export const FINGERPRINT_POOL: ReadonlyArray = [ { userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", platform: "Win32", diff --git a/packages/browser/src/pool.ts b/packages/browser/src/pool.ts index 3a6cce2..95fad3a 100644 --- a/packages/browser/src/pool.ts +++ b/packages/browser/src/pool.ts @@ -1,4 +1,4 @@ -import type { PoolBrowser, PoolStats } from "@trawl/types" +import type { BrowserHandle, PoolBrowser, PoolStats } from "@trawl/types" import { Camoufox } from "camoufox-js" import { FINGERPRINT_POOL } from "./fingerprint" @@ -18,16 +18,9 @@ export class PoolExhaustedError extends Error { } } -export interface BrowserHandle { - id: number - context: BrowserContext - browser: Browser - // Per-instance HTTP-level fingerprint (User-Agent + matching navigator.platform / - // locale / timezone). Set at init from FINGERPRINT_POOL so the orchestrator can - // send a UA that matches this browser's actual Camoufox-generated platform. - fingerprint: (typeof FINGERPRINT_POOL)[number] - noteTemporaryContext?: (reason: string) => void -} +// BrowserHandle now lives in @trawl/types (shared cross-package); re-exported here +// for backward compat so existing `import type { BrowserHandle } from "@trawl/browser"` keeps working. +export type { BrowserHandle } from "@trawl/types" interface PoolEntry extends PoolBrowser { browser: Browser | null diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index b9fc8ea..7f51821 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -9,6 +9,13 @@ export interface Cookie { sameSite?: string } +// CONNECT is intentionally excluded — it's a tunneling verb, not a normal +// request body, and would let a caller establish arbitrary TCP tunnels. +// QUERY (RFC 9341) is included — safe verb, body carries the query params. +// Single source of truth for the request-method union — @trawl/tiers derives its +// runtime SUPPORTED_METHODS array from this same literal set (see sanitize.ts). +export type SupportedMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" | "TRACE" | "QUERY" + export interface ScrapeRequest { url: string maxTimeout?: number @@ -16,10 +23,7 @@ export interface ScrapeRequest { maxTier?: 1 | 2 | 3 | 4 sessionId?: string headers?: Record - // CONNECT is intentionally excluded — it's a tunneling verb, not a normal - // request body, and would let a caller establish arbitrary TCP tunnels. - // QUERY (RFC 9341) is included — safe verb, body carries the query params. - method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "HEAD" | "OPTIONS" | "TRACE" | "QUERY" + method?: SupportedMethod body?: string // Per-request proxy override — bypasses the server-configured proxy pool for this call. proxy?: string @@ -69,6 +73,30 @@ export interface PoolStats { avgRestarts: number } +// Per-instance HTTP-level fingerprint (User-Agent + matching navigator.platform / +// locale / timezone) — @trawl/browser's FINGERPRINT_POOL is typed against this shape. +export interface BrowserFingerprint { + userAgent: string + platform: "Win32" | "MacIntel" | "Linux x86_64" | "Linux armv8" + locale: string + timezone: string +} + +// A leased browser+context pair handed to a tier by @trawl/browser's BrowserPool. +// `context`/`browser` are `any` — camoufox-js doesn't export Playwright's +// Browser/BrowserContext types, and browsers from Playwright vs patchright aren't +// structurally assignable to each other, so `any` is the pragmatic escape hatch +// (consumers call .newPage()/.newContext()/.cookies() etc directly on these fields). +export interface BrowserHandle { + id: number + // biome-ignore lint/suspicious/noExplicitAny: see comment above + context: any + // biome-ignore lint/suspicious/noExplicitAny: see comment above + browser: any + fingerprint: BrowserFingerprint + noteTemporaryContext?: (reason: string) => void +} + // Per-request proxy override as it arrives at the API. Prowlarr's Cardigann flow // serializes this as an object (its FlareSolverrProxy class: {url, username, password}). // Other callers may send a plain URL string. The API boundary normalizes both forms