chore: migrate to oxlint and oxfmt
Co-authored-by: Christoph Nakazawa <christoph.pojer@gmail.com>
This commit is contained in:
@@ -21,12 +21,7 @@ export function isActKind(value: unknown): value is ActKind {
|
||||
}
|
||||
|
||||
export type ClickButton = "left" | "right" | "middle";
|
||||
export type ClickModifier =
|
||||
| "Alt"
|
||||
| "Control"
|
||||
| "ControlOrMeta"
|
||||
| "Meta"
|
||||
| "Shift";
|
||||
export type ClickModifier = "Alt" | "Control" | "ControlOrMeta" | "Meta" | "Shift";
|
||||
|
||||
const ALLOWED_CLICK_MODIFIERS = new Set<ClickModifier>([
|
||||
"Alt",
|
||||
@@ -45,9 +40,7 @@ export function parseClickModifiers(raw: string[]): {
|
||||
modifiers?: ClickModifier[];
|
||||
error?: string;
|
||||
} {
|
||||
const invalid = raw.filter(
|
||||
(m) => !ALLOWED_CLICK_MODIFIERS.has(m as ClickModifier),
|
||||
);
|
||||
const invalid = raw.filter((m) => !ALLOWED_CLICK_MODIFIERS.has(m as ClickModifier));
|
||||
if (invalid.length) {
|
||||
return { error: "modifiers must be Alt|Control|ControlOrMeta|Meta|Shift" };
|
||||
}
|
||||
|
||||
@@ -15,18 +15,9 @@ import {
|
||||
resolveProfileContext,
|
||||
SELECTOR_UNSUPPORTED_MESSAGE,
|
||||
} from "./agent.shared.js";
|
||||
import {
|
||||
jsonError,
|
||||
toBoolean,
|
||||
toNumber,
|
||||
toStringArray,
|
||||
toStringOrEmpty,
|
||||
} from "./utils.js";
|
||||
import { jsonError, toBoolean, toNumber, toStringArray, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserAgentActRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserAgentActRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
app.post("/act", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
@@ -55,8 +46,7 @@ export function registerBrowserAgentActRoutes(
|
||||
const timeoutMs = toNumber(body.timeoutMs);
|
||||
const buttonRaw = toStringOrEmpty(body.button) || "";
|
||||
const button = buttonRaw ? parseClickButton(buttonRaw) : undefined;
|
||||
if (buttonRaw && !button)
|
||||
return jsonError(res, 400, "button must be left|right|middle");
|
||||
if (buttonRaw && !button) return jsonError(res, 400, "button must be left|right|middle");
|
||||
|
||||
const modifiersRaw = toStringArray(body.modifiers) ?? [];
|
||||
const parsedModifiers = parseClickModifiers(modifiersRaw);
|
||||
@@ -79,8 +69,7 @@ export function registerBrowserAgentActRoutes(
|
||||
case "type": {
|
||||
const ref = toStringOrEmpty(body.ref);
|
||||
if (!ref) return jsonError(res, 400, "ref is required");
|
||||
if (typeof body.text !== "string")
|
||||
return jsonError(res, 400, "text is required");
|
||||
if (typeof body.text !== "string") return jsonError(res, 400, "text is required");
|
||||
const text = body.text;
|
||||
const submit = toBoolean(body.submit) ?? false;
|
||||
const slowly = toBoolean(body.slowly) ?? false;
|
||||
@@ -125,9 +114,7 @@ export function registerBrowserAgentActRoutes(
|
||||
const ref = toStringOrEmpty(body.ref);
|
||||
if (!ref) return jsonError(res, 400, "ref is required");
|
||||
const timeoutMs = toNumber(body.timeoutMs);
|
||||
const scrollRequest: Parameters<
|
||||
typeof pw.scrollIntoViewViaPlaywright
|
||||
>[0] = {
|
||||
const scrollRequest: Parameters<typeof pw.scrollIntoViewViaPlaywright>[0] = {
|
||||
cdpUrl,
|
||||
targetId: tab.targetId,
|
||||
ref,
|
||||
@@ -139,8 +126,7 @@ export function registerBrowserAgentActRoutes(
|
||||
case "drag": {
|
||||
const startRef = toStringOrEmpty(body.startRef);
|
||||
const endRef = toStringOrEmpty(body.endRef);
|
||||
if (!startRef || !endRef)
|
||||
return jsonError(res, 400, "startRef and endRef are required");
|
||||
if (!startRef || !endRef) return jsonError(res, 400, "startRef and endRef are required");
|
||||
const timeoutMs = toNumber(body.timeoutMs);
|
||||
await pw.dragViaPlaywright({
|
||||
cdpUrl,
|
||||
@@ -154,8 +140,7 @@ export function registerBrowserAgentActRoutes(
|
||||
case "select": {
|
||||
const ref = toStringOrEmpty(body.ref);
|
||||
const values = toStringArray(body.values);
|
||||
if (!ref || !values?.length)
|
||||
return jsonError(res, 400, "ref and values are required");
|
||||
if (!ref || !values?.length) return jsonError(res, 400, "ref and values are required");
|
||||
const timeoutMs = toNumber(body.timeoutMs);
|
||||
await pw.selectOptionViaPlaywright({
|
||||
cdpUrl,
|
||||
@@ -199,8 +184,7 @@ export function registerBrowserAgentActRoutes(
|
||||
case "resize": {
|
||||
const width = toNumber(body.width);
|
||||
const height = toNumber(body.height);
|
||||
if (!width || !height)
|
||||
return jsonError(res, 400, "width and height are required");
|
||||
if (!width || !height) return jsonError(res, 400, "width and height are required");
|
||||
await pw.resizeViewportViaPlaywright({
|
||||
cdpUrl,
|
||||
targetId: tab.targetId,
|
||||
@@ -300,11 +284,7 @@ export function registerBrowserAgentActRoutes(
|
||||
if (!pw) return;
|
||||
if (inputRef || element) {
|
||||
if (ref) {
|
||||
return jsonError(
|
||||
res,
|
||||
400,
|
||||
"ref cannot be combined with inputRef/element",
|
||||
);
|
||||
return jsonError(res, 400, "ref cannot be combined with inputRef/element");
|
||||
}
|
||||
await pw.setInputFilesViaPlaywright({
|
||||
cdpUrl: profileCtx.profile.cdpUrl,
|
||||
|
||||
@@ -5,23 +5,14 @@ import path from "node:path";
|
||||
import type express from "express";
|
||||
|
||||
import type { BrowserRouteContext } from "../server-context.js";
|
||||
import {
|
||||
handleRouteError,
|
||||
readBody,
|
||||
requirePwAi,
|
||||
resolveProfileContext,
|
||||
} from "./agent.shared.js";
|
||||
import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js";
|
||||
import { toBoolean, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserAgentDebugRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserAgentDebugRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
app.get("/console", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const level = typeof req.query.level === "string" ? req.query.level : "";
|
||||
|
||||
try {
|
||||
@@ -42,8 +33,7 @@ export function registerBrowserAgentDebugRoutes(
|
||||
app.get("/errors", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const clear = toBoolean(req.query.clear) ?? false;
|
||||
|
||||
try {
|
||||
@@ -64,8 +54,7 @@ export function registerBrowserAgentDebugRoutes(
|
||||
app.get("/requests", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const filter = typeof req.query.filter === "string" ? req.query.filter : "";
|
||||
const clear = toBoolean(req.query.clear) ?? false;
|
||||
|
||||
|
||||
@@ -19,11 +19,7 @@ export function readBody(req: express.Request): Record<string, unknown> {
|
||||
return body;
|
||||
}
|
||||
|
||||
export function handleRouteError(
|
||||
ctx: BrowserRouteContext,
|
||||
res: express.Response,
|
||||
err: unknown,
|
||||
) {
|
||||
export function handleRouteError(ctx: BrowserRouteContext, res: express.Response, err: unknown) {
|
||||
const mapped = ctx.mapTabError(err);
|
||||
if (mapped) return jsonError(res, mapped.status, mapped.message);
|
||||
jsonError(res, 500, String(err));
|
||||
|
||||
@@ -20,10 +20,7 @@ import {
|
||||
} from "./agent.shared.js";
|
||||
import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserAgentSnapshotRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserAgentSnapshotRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
app.post("/navigate", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
@@ -88,11 +85,7 @@ export function registerBrowserAgentSnapshotRoutes(
|
||||
const type = body.type === "jpeg" ? "jpeg" : "png";
|
||||
|
||||
if (fullPage && (ref || element)) {
|
||||
return jsonError(
|
||||
res,
|
||||
400,
|
||||
"fullPage is not supported for element screenshots",
|
||||
);
|
||||
return jsonError(res, 400, "fullPage is not supported for element screenshots");
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -144,8 +137,7 @@ export function registerBrowserAgentSnapshotRoutes(
|
||||
app.get("/snapshot", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const format =
|
||||
req.query.format === "aria"
|
||||
? "aria"
|
||||
@@ -154,26 +146,17 @@ export function registerBrowserAgentSnapshotRoutes(
|
||||
: (await getPwAiModule())
|
||||
? "ai"
|
||||
: "aria";
|
||||
const limitRaw =
|
||||
typeof req.query.limit === "string" ? Number(req.query.limit) : undefined;
|
||||
const limitRaw = typeof req.query.limit === "string" ? Number(req.query.limit) : undefined;
|
||||
const hasMaxChars = Object.hasOwn(req.query, "maxChars");
|
||||
const maxCharsRaw =
|
||||
typeof req.query.maxChars === "string"
|
||||
? Number(req.query.maxChars)
|
||||
: undefined;
|
||||
typeof req.query.maxChars === "string" ? Number(req.query.maxChars) : undefined;
|
||||
const limit = Number.isFinite(limitRaw) ? limitRaw : undefined;
|
||||
const maxChars =
|
||||
typeof maxCharsRaw === "number" &&
|
||||
Number.isFinite(maxCharsRaw) &&
|
||||
maxCharsRaw > 0
|
||||
typeof maxCharsRaw === "number" && Number.isFinite(maxCharsRaw) && maxCharsRaw > 0
|
||||
? Math.floor(maxCharsRaw)
|
||||
: undefined;
|
||||
const resolvedMaxChars =
|
||||
format === "ai"
|
||||
? hasMaxChars
|
||||
? maxChars
|
||||
: DEFAULT_AI_SNAPSHOT_MAX_CHARS
|
||||
: undefined;
|
||||
format === "ai" ? (hasMaxChars ? maxChars : DEFAULT_AI_SNAPSHOT_MAX_CHARS) : undefined;
|
||||
const interactive = toBoolean(req.query.interactive);
|
||||
const compact = toBoolean(req.query.compact);
|
||||
const depth = toNumber(req.query.depth);
|
||||
@@ -208,9 +191,7 @@ export function registerBrowserAgentSnapshotRoutes(
|
||||
.snapshotAiViaPlaywright({
|
||||
cdpUrl: profileCtx.profile.cdpUrl,
|
||||
targetId: tab.targetId,
|
||||
...(typeof resolvedMaxChars === "number"
|
||||
? { maxChars: resolvedMaxChars }
|
||||
: {}),
|
||||
...(typeof resolvedMaxChars === "number" ? { maxChars: resolvedMaxChars } : {}),
|
||||
})
|
||||
.catch(async (err) => {
|
||||
// Public-API fallback when Playwright's private _snapshotForAI is missing.
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import type express from "express";
|
||||
|
||||
import type { BrowserRouteContext } from "../server-context.js";
|
||||
import {
|
||||
handleRouteError,
|
||||
readBody,
|
||||
requirePwAi,
|
||||
resolveProfileContext,
|
||||
} from "./agent.shared.js";
|
||||
import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js";
|
||||
import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserAgentStorageRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserAgentStorageRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
app.get("/cookies", async (req, res) => {
|
||||
const profileCtx = resolveProfileContext(req, res, ctx);
|
||||
if (!profileCtx) return;
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
|
||||
const pw = await requirePwAi(res, "cookies");
|
||||
@@ -38,9 +29,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const body = readBody(req);
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const cookie =
|
||||
body.cookie &&
|
||||
typeof body.cookie === "object" &&
|
||||
!Array.isArray(body.cookie)
|
||||
body.cookie && typeof body.cookie === "object" && !Array.isArray(body.cookie)
|
||||
? (body.cookie as Record<string, unknown>)
|
||||
: null;
|
||||
if (!cookie) return jsonError(res, 400, "cookie is required");
|
||||
@@ -61,9 +50,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
httpOnly: toBoolean(cookie.httpOnly) ?? undefined,
|
||||
secure: toBoolean(cookie.secure) ?? undefined,
|
||||
sameSite:
|
||||
cookie.sameSite === "Lax" ||
|
||||
cookie.sameSite === "None" ||
|
||||
cookie.sameSite === "Strict"
|
||||
cookie.sameSite === "Lax" || cookie.sameSite === "None" || cookie.sameSite === "Strict"
|
||||
? (cookie.sameSite as "Lax" | "None" | "Strict")
|
||||
: undefined,
|
||||
},
|
||||
@@ -99,8 +86,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const kind = toStringOrEmpty(req.params.kind);
|
||||
if (kind !== "local" && kind !== "session")
|
||||
return jsonError(res, 400, "kind must be local|session");
|
||||
const targetId =
|
||||
typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
|
||||
const key = typeof req.query.key === "string" ? req.query.key : "";
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
|
||||
@@ -175,8 +161,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const body = readBody(req);
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const offline = toBoolean(body.offline);
|
||||
if (offline === undefined)
|
||||
return jsonError(res, 400, "offline is required");
|
||||
if (offline === undefined) return jsonError(res, 400, "offline is required");
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId);
|
||||
const pw = await requirePwAi(res, "offline");
|
||||
@@ -198,9 +183,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const body = readBody(req);
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const headers =
|
||||
body.headers &&
|
||||
typeof body.headers === "object" &&
|
||||
!Array.isArray(body.headers)
|
||||
body.headers && typeof body.headers === "object" && !Array.isArray(body.headers)
|
||||
? (body.headers as Record<string, unknown>)
|
||||
: null;
|
||||
if (!headers) return jsonError(res, 400, "headers is required");
|
||||
@@ -230,8 +213,7 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const clear = toBoolean(body.clear) ?? false;
|
||||
const username = toStringOrEmpty(body.username) || undefined;
|
||||
const password =
|
||||
typeof body.password === "string" ? body.password : undefined;
|
||||
const password = typeof body.password === "string" ? body.password : undefined;
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId);
|
||||
const pw = await requirePwAi(res, "http credentials");
|
||||
@@ -285,19 +267,13 @@ export function registerBrowserAgentStorageRoutes(
|
||||
const targetId = toStringOrEmpty(body.targetId) || undefined;
|
||||
const schemeRaw = toStringOrEmpty(body.colorScheme);
|
||||
const colorScheme =
|
||||
schemeRaw === "dark" ||
|
||||
schemeRaw === "light" ||
|
||||
schemeRaw === "no-preference"
|
||||
schemeRaw === "dark" || schemeRaw === "light" || schemeRaw === "no-preference"
|
||||
? (schemeRaw as "dark" | "light" | "no-preference")
|
||||
: schemeRaw === "none"
|
||||
? null
|
||||
: undefined;
|
||||
if (colorScheme === undefined)
|
||||
return jsonError(
|
||||
res,
|
||||
400,
|
||||
"colorScheme must be dark|light|no-preference|none",
|
||||
);
|
||||
return jsonError(res, 400, "colorScheme must be dark|light|no-preference|none");
|
||||
try {
|
||||
const tab = await profileCtx.ensureTabAvailable(targetId);
|
||||
const pw = await requirePwAi(res, "media emulation");
|
||||
|
||||
@@ -6,10 +6,7 @@ import { registerBrowserAgentDebugRoutes } from "./agent.debug.js";
|
||||
import { registerBrowserAgentSnapshotRoutes } from "./agent.snapshot.js";
|
||||
import { registerBrowserAgentStorageRoutes } from "./agent.storage.js";
|
||||
|
||||
export function registerBrowserAgentRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserAgentRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
registerBrowserAgentSnapshotRoutes(app, ctx);
|
||||
registerBrowserAgentActRoutes(app, ctx);
|
||||
registerBrowserAgentDebugRoutes(app, ctx);
|
||||
|
||||
@@ -4,10 +4,7 @@ import { createBrowserProfilesService } from "../profiles-service.js";
|
||||
import type { BrowserRouteContext } from "../server-context.js";
|
||||
import { getProfileContext, jsonError, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserBasicRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserBasicRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
// List all profiles with their status
|
||||
app.get("/profiles", async (_req, res) => {
|
||||
try {
|
||||
|
||||
@@ -5,10 +5,7 @@ import { registerBrowserAgentRoutes } from "./agent.js";
|
||||
import { registerBrowserBasicRoutes } from "./basic.js";
|
||||
import { registerBrowserTabRoutes } from "./tabs.js";
|
||||
|
||||
export function registerBrowserRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
registerBrowserBasicRoutes(app, ctx);
|
||||
registerBrowserTabRoutes(app, ctx);
|
||||
registerBrowserAgentRoutes(app, ctx);
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
import type express from "express";
|
||||
|
||||
import type { BrowserRouteContext } from "../server-context.js";
|
||||
import {
|
||||
getProfileContext,
|
||||
jsonError,
|
||||
toNumber,
|
||||
toStringOrEmpty,
|
||||
} from "./utils.js";
|
||||
import { getProfileContext, jsonError, toNumber, toStringOrEmpty } from "./utils.js";
|
||||
|
||||
export function registerBrowserTabRoutes(
|
||||
app: express.Express,
|
||||
ctx: BrowserRouteContext,
|
||||
) {
|
||||
export function registerBrowserTabRoutes(app: express.Express, ctx: BrowserRouteContext) {
|
||||
app.get("/tabs", async (req, res) => {
|
||||
const profileCtx = getProfileContext(req, ctx);
|
||||
if ("error" in profileCtx)
|
||||
return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
try {
|
||||
const reachable = await profileCtx.isReachable(300);
|
||||
if (!reachable)
|
||||
return res.json({ running: false, tabs: [] as unknown[] });
|
||||
if (!reachable) return res.json({ running: false, tabs: [] as unknown[] });
|
||||
const tabs = await profileCtx.listTabs();
|
||||
res.json({ running: true, tabs });
|
||||
} catch (err) {
|
||||
@@ -29,8 +19,7 @@ export function registerBrowserTabRoutes(
|
||||
|
||||
app.post("/tabs/open", async (req, res) => {
|
||||
const profileCtx = getProfileContext(req, ctx);
|
||||
if ("error" in profileCtx)
|
||||
return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
const url = toStringOrEmpty((req.body as { url?: unknown })?.url);
|
||||
if (!url) return jsonError(res, 400, "url is required");
|
||||
try {
|
||||
@@ -44,15 +33,11 @@ export function registerBrowserTabRoutes(
|
||||
|
||||
app.post("/tabs/focus", async (req, res) => {
|
||||
const profileCtx = getProfileContext(req, ctx);
|
||||
if ("error" in profileCtx)
|
||||
return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
const targetId = toStringOrEmpty(
|
||||
(req.body as { targetId?: unknown })?.targetId,
|
||||
);
|
||||
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
const targetId = toStringOrEmpty((req.body as { targetId?: unknown })?.targetId);
|
||||
if (!targetId) return jsonError(res, 400, "targetId is required");
|
||||
try {
|
||||
if (!(await profileCtx.isReachable(300)))
|
||||
return jsonError(res, 409, "browser not running");
|
||||
if (!(await profileCtx.isReachable(300))) return jsonError(res, 409, "browser not running");
|
||||
await profileCtx.focusTab(targetId);
|
||||
res.json({ ok: true });
|
||||
} catch (err) {
|
||||
@@ -64,13 +49,11 @@ export function registerBrowserTabRoutes(
|
||||
|
||||
app.delete("/tabs/:targetId", async (req, res) => {
|
||||
const profileCtx = getProfileContext(req, ctx);
|
||||
if ("error" in profileCtx)
|
||||
return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
const targetId = toStringOrEmpty(req.params.targetId);
|
||||
if (!targetId) return jsonError(res, 400, "targetId is required");
|
||||
try {
|
||||
if (!(await profileCtx.isReachable(300)))
|
||||
return jsonError(res, 409, "browser not running");
|
||||
if (!(await profileCtx.isReachable(300))) return jsonError(res, 409, "browser not running");
|
||||
await profileCtx.closeTab(targetId);
|
||||
res.json({ ok: true });
|
||||
} catch (err) {
|
||||
@@ -82,8 +65,7 @@ export function registerBrowserTabRoutes(
|
||||
|
||||
app.post("/tabs/action", async (req, res) => {
|
||||
const profileCtx = getProfileContext(req, ctx);
|
||||
if ("error" in profileCtx)
|
||||
return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error);
|
||||
const action = toStringOrEmpty((req.body as { action?: unknown })?.action);
|
||||
const index = toNumber((req.body as { index?: unknown })?.index);
|
||||
try {
|
||||
@@ -109,8 +91,7 @@ export function registerBrowserTabRoutes(
|
||||
}
|
||||
|
||||
if (action === "select") {
|
||||
if (typeof index !== "number")
|
||||
return jsonError(res, 400, "index is required");
|
||||
if (typeof index !== "number") return jsonError(res, 400, "index is required");
|
||||
const tabs = await profileCtx.listTabs();
|
||||
const target = tabs[index];
|
||||
if (!target) return jsonError(res, 404, "tab not found");
|
||||
|
||||
@@ -32,11 +32,7 @@ export function getProfileContext(
|
||||
}
|
||||
}
|
||||
|
||||
export function jsonError(
|
||||
res: express.Response,
|
||||
status: number,
|
||||
message: string,
|
||||
) {
|
||||
export function jsonError(res: express.Response, status: number, message: string) {
|
||||
res.status(status).json({ error: message });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user