refactor: attach and windowId become session methods cdp/attach.ts and cdp/window.ts were a module each for a single `map(await session.callBrowser(...))` one-liner that took the session as its first argument — two files, two imports and two names for what the session can expose itself. They are now session.attach(targetId) and session.windowId(targetId). session.ts also repeated `targetId ? tabs.get(targetId) : undefined` eight times; that is now currentTab(). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
amankumarsingh77 amankumarsingh7702@gmail.com
Tue, 28 Jul 2026 22:01:47 +0530
6 files changed,
31 insertions(+),
47 deletions(-)
D
src/cdp/attach.ts
@@ -1,12 +0,0 @@
-import { map, type Result } from "../util/result"; -import type { CdpError } from "./errors"; -import type { CdpSession } from "./session"; - -export const attachTo = async ( - session: CdpSession, - targetId: string, -): Promise<Result<string, CdpError>> => - map( - await session.callBrowser("Target.attachToTarget", { targetId, flatten: true }), - (d) => d.sessionId, - );
M
src/cdp/session.ts
→
src/cdp/session.ts
@@ -1,4 +1,4 @@
-import { type Result, ok } from "../util/result"; +import { map, type Result, ok } from "../util/result"; import type { CdpError } from "./errors"; import type { DialogInfo } from "./types"; import type { OwnershipRegistry } from "./ownership";@@ -7,8 +7,6 @@ import { type CdpMethod, type ParamsOf, type ResultOf, decodeResult } from "./commands";
import { decodeEvent } from "./events"; import { createNetworkBuffer, type DrainResult, type NetworkFilter } from "./network-buffer"; import { createConsoleBuffer, type ConsoleDrainResult, type ConsoleFilter } from "./console-buffer"; -import { attachTo } from "./attach"; -import { getWindowId } from "./window"; type TabSession = { sessionId: string;@@ -26,6 +24,8 @@ raw === "confirm" || raw === "prompt" || raw === "beforeunload" ? raw : "alert";
export type CdpSession = { attachFirstPage(): Promise<Result<{ readonly targetId: string; readonly sessionId: string }, CdpError>>; + attach(targetId: string): Promise<Result<string, CdpError>>; + windowId(targetId: string): Promise<Result<number, CdpError>>; switchTo(targetId: string): Promise<Result<void, CdpError>>; current(): { readonly sessionId: string; readonly targetId: string } | null; setRefMap(refMap: Map<string, number>, refSig: Map<string, string>): void;@@ -185,6 +185,14 @@ if (!raw.success) return raw;
return decodeResult(method, raw.data); }; + const attach = async (tid: string): Promise<Result<string, CdpError>> => + map(await req("Target.attachToTarget", { targetId: tid, flatten: true }, null), (d) => d.sessionId); + + const windowId = async (tid: string): Promise<Result<number, CdpError>> => + map(await req("Browser.getWindowForTarget", { targetId: tid }, null), (d) => d.windowId); + + const currentTab = (): TabSession | undefined => (targetId ? tabs.get(targetId) : undefined); + const session: CdpSession = { async attachFirstPage() { await req("Target.setDiscoverTargets", { discover: true }, null);@@ -203,7 +211,7 @@ const anchorId = survivors[0];
if (anchorId === undefined) { ownership.setHarnessWindowId(undefined); } else { - const anchorWin = await getWindowId(session, anchorId); + const anchorWin = await windowId(anchorId); if (anchorWin.success) { const anchorWindowId = anchorWin.data; ownership.setHarnessWindowId(anchorWindowId);@@ -211,7 +219,7 @@ const windows = await Promise.all(
allPages.map((p) => p.targetId === anchorId ? Promise.resolve(anchorWin) - : getWindowId(session, p.targetId), + : windowId(p.targetId), ), ); allPages.forEach((p, i) => {@@ -254,12 +262,12 @@ pickTargetId = created.data.targetId;
if (ownership) { ownership.setHarnessWindow(created.data.targetId); ownership.add(created.data.targetId); - const win = await getWindowId(session, created.data.targetId); + const win = await windowId(created.data.targetId); if (win.success) ownership.setHarnessWindowId(win.data); } } - const attached = await attachTo(session, pickTargetId); + const attached = await attach(pickTargetId); if (!attached.success) return attached; const attachedSessionId = attached.data; sessionId = attachedSessionId;@@ -281,7 +289,7 @@ },
async switchTo(tid) { const activated = await req("Target.activateTarget", { targetId: tid }, null); if (!activated.success) return activated; - const attached = await attachTo(session, tid); + const attached = await attach(tid); if (!attached.success) return attached; const attachedSessionId = attached.data; const existing = tabs.get(tid);@@ -307,25 +315,27 @@ sessionId = tab.sessionId;
targetId = tid; return ok(undefined); }, + attach, + windowId, current() { return sessionId && targetId ? { sessionId, targetId } : null; }, setRefMap(refMap, refSig) { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); if (!tab) return; tab.refMap = refMap; tab.refSig = refSig; }, resolveRef(ref) { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); return tab?.refMap.get(ref); }, refSignatures() { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); return tab?.refSig ?? new Map(); }, refMappings() { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); return tab?.refMap ?? new Map(); }, call(method, params, opts) {@@ -338,26 +348,26 @@ callBrowser(method, params, opts) {
return req(method, params, null, opts); }, takeDialog() { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); if (!tab) return null; const d = tab.dialog; tab.dialog = null; return d; }, drainPageInfoInvalidations() { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); if (!tab) return false; const dirty = tab.pageInfoDirty; tab.pageInfoDirty = false; return dirty; }, drainNetworkBuffer(filter) { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); if (!tab) return { records: [], total: 0, bufferOverflowed: false }; return tab.networkBuffer.drain(filter); }, drainConsoleBuffer(filter) { - const tab = targetId ? tabs.get(targetId) : undefined; + const tab = currentTab(); if (!tab) return { records: [], total: 0, bufferOverflowed: false }; return tab.consoleBuffer.drain(filter); },
M
src/cdp/target-factory.ts
→
src/cdp/target-factory.ts
@@ -3,9 +3,7 @@
import { randomUUID } from "node:crypto"; import type { BrowserClient } from "../client"; import { type Result, err, ok } from "../util/result"; -import { attachTo } from "./attach"; import { type CdpError, cdpError } from "./errors"; -import { getWindowId } from "./window"; const SPAWN_DEADLINE_MS = 8_000; const SPAWN_POLL_MS = 100;@@ -31,7 +29,7 @@
const sessionForTarget = async (client: BrowserClient, targetId: string): Promise<Result<string, CdpError>> => { const current = client.current(); if (current?.targetId === targetId) return ok(current.sessionId); - return attachTo(client.session(), targetId); + return client.session().attach(targetId); }; const spawnTabViaOpener = async (@@ -130,7 +128,7 @@ const { targetId } = created.data;
const ownership = client.ownership(); ownership.setHarnessWindow(targetId); ownership.add(targetId); - const win = await getWindowId(client.session(), targetId); + const win = await client.session().windowId(targetId); if (win.success) ownership.setHarnessWindowId(win.data); return ok(targetId); };
D
src/cdp/window.ts
@@ -1,9 +0,0 @@
-import { map, type Result } from "../util/result"; -import type { CdpError } from "./errors"; -import type { CdpSession } from "./session"; - -export const getWindowId = async ( - session: CdpSession, - targetId: string, -): Promise<Result<number, CdpError>> => - map(await session.callBrowser("Browser.getWindowForTarget", { targetId }), (d) => d.windowId);
M
src/profile/bind.ts
→
src/profile/bind.ts
@@ -1,8 +1,6 @@
import type { BrowserClient } from "../client"; -import { attachTo } from "../cdp/attach"; import type { ResultOf } from "../cdp/commands"; import { type CdpError, cdpError } from "../cdp/errors"; -import { getWindowId } from "../cdp/window"; import { type Result, err, ok } from "../util/result"; import { detectRunningBrowser, resolveBrowserExecutable } from "./browser-process"; import { openProfileWindow } from "./launch";@@ -79,10 +77,10 @@
const ownership = client.ownership(); ownership.setHarnessWindow(seed.targetId); ownership.add(seed.targetId); - const win = await getWindowId(client.session(), seed.targetId); + const win = await client.session().windowId(seed.targetId); if (win.success) ownership.setHarnessWindowId(win.data); - const attached = await attachTo(client.session(), seed.targetId); + const attached = await client.session().attach(seed.targetId); if (attached.success) { await client.session().callOnTarget("Page.navigate", { url: "about:blank" }, attached.data); }