refactor: share browser runtime helpers

This commit is contained in:
Peter Steinberger
2026-04-20 16:32:16 +01:00
parent 21fbe416d4
commit 76052a4e01
3 changed files with 31 additions and 46 deletions

View File

@@ -1,3 +1,4 @@
import { buildProfileQuery, withBaseUrl } from "./client-actions-url.js";
import { fetchBrowserJson } from "./client-fetch.js";
import type { BrowserTab, BrowserTransport, SnapshotAriaNode } from "./client.types.js";
@@ -77,18 +78,6 @@ export type SnapshotResult =
imageType?: "png" | "jpeg";
};
function buildProfileQuery(profile?: string): string {
return profile ? `?profile=${encodeURIComponent(profile)}` : "";
}
function withBaseUrl(baseUrl: string | undefined, path: string): string {
const trimmed = baseUrl?.trim();
if (!trimmed) {
return path;
}
return `${trimmed.replace(/\/$/, "")}${path}`;
}
export async function browserStatus(
baseUrl?: string,
opts?: { profile?: string },

View File

@@ -2,7 +2,7 @@ import fs from "node:fs";
import type { ResolvedBrowserProfile } from "./config.js";
import { BrowserResetUnsupportedError } from "./errors.js";
import { getBrowserProfileCapabilities } from "./profile-capabilities.js";
import { getPwAiModule } from "./pw-ai-module.js";
import { closePlaywrightBrowserConnectionForProfile } from "./server-context.lifecycle.js";
import type { ProfileRuntimeState } from "./server-context.types.js";
import { movePathToTrash } from "./trash.js";
@@ -18,15 +18,6 @@ type ResetOps = {
resetProfile: () => Promise<{ moved: boolean; from: string; to?: string }>;
};
async function closePlaywrightBrowserConnectionForProfile(cdpUrl?: string): Promise<void> {
try {
const mod = await getPwAiModule({ mode: "soft" });
await mod?.closePlaywrightBrowserConnection(cdpUrl ? { cdpUrl } : undefined);
} catch {
// ignore
}
}
export function createProfileResetOps({
profile,
getProfileState,

View File

@@ -38,6 +38,25 @@ function toTrackedTabId(params: { targetId: string; baseUrl?: string; profile?:
return `${params.targetId}\u0000${params.baseUrl ?? ""}\u0000${params.profile ?? ""}`;
}
function resolveTrackedTabIdentity(params: {
sessionKey?: string;
targetId?: string;
baseUrl?: string;
profile?: string;
}): Omit<TrackedSessionBrowserTab, "trackedAt"> | undefined {
const sessionKeyRaw = params.sessionKey?.trim();
const targetIdRaw = params.targetId?.trim();
if (!sessionKeyRaw || !targetIdRaw) {
return undefined;
}
return {
sessionKey: normalizeSessionKey(sessionKeyRaw),
targetId: normalizeTargetId(targetIdRaw),
baseUrl: normalizeBaseUrl(params.baseUrl),
profile: normalizeProfile(params.profile),
};
}
function isIgnorableCloseError(err: unknown): boolean {
const message = normalizeLowercaseStringOrEmpty(String(err));
return (
@@ -54,27 +73,19 @@ export function trackSessionBrowserTab(params: {
baseUrl?: string;
profile?: string;
}): void {
const sessionKeyRaw = params.sessionKey?.trim();
const targetIdRaw = params.targetId?.trim();
if (!sessionKeyRaw || !targetIdRaw) {
const identity = resolveTrackedTabIdentity(params);
if (!identity) {
return;
}
const sessionKey = normalizeSessionKey(sessionKeyRaw);
const targetId = normalizeTargetId(targetIdRaw);
const baseUrl = normalizeBaseUrl(params.baseUrl);
const profile = normalizeProfile(params.profile);
const tracked: TrackedSessionBrowserTab = {
sessionKey,
targetId,
baseUrl,
profile,
...identity,
trackedAt: Date.now(),
};
const trackedId = toTrackedTabId(tracked);
let trackedForSession = trackedTabsBySession.get(sessionKey);
let trackedForSession = trackedTabsBySession.get(identity.sessionKey);
if (!trackedForSession) {
trackedForSession = new Map();
trackedTabsBySession.set(sessionKey, trackedForSession);
trackedTabsBySession.set(identity.sessionKey, trackedForSession);
}
trackedForSession.set(trackedId, tracked);
}
@@ -85,24 +96,18 @@ export function untrackSessionBrowserTab(params: {
baseUrl?: string;
profile?: string;
}): void {
const sessionKeyRaw = params.sessionKey?.trim();
const targetIdRaw = params.targetId?.trim();
if (!sessionKeyRaw || !targetIdRaw) {
const identity = resolveTrackedTabIdentity(params);
if (!identity) {
return;
}
const sessionKey = normalizeSessionKey(sessionKeyRaw);
const trackedForSession = trackedTabsBySession.get(sessionKey);
const trackedForSession = trackedTabsBySession.get(identity.sessionKey);
if (!trackedForSession) {
return;
}
const trackedId = toTrackedTabId({
targetId: normalizeTargetId(targetIdRaw),
baseUrl: normalizeBaseUrl(params.baseUrl),
profile: normalizeProfile(params.profile),
});
const trackedId = toTrackedTabId(identity);
trackedForSession.delete(trackedId);
if (trackedForSession.size === 0) {
trackedTabsBySession.delete(sessionKey);
trackedTabsBySession.delete(identity.sessionKey);
}
}