@xbrowser/cli 1.0.9 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -20,7 +20,7 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-EUHVZVVL.js";
23
+ } from "./chunk-MWBVZWXA.js";
24
24
  import "./chunk-IX4JY6OO.js";
25
25
  import "./chunk-TNEN6VQ2.js";
26
26
  import "./chunk-GDKLH7ZY.js";
@@ -20,7 +20,7 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-JUNEBEGF.js";
23
+ } from "./chunk-GOKTOYWM.js";
24
24
  import "./chunk-IX4JY6OO.js";
25
25
  import "./chunk-TNEN6VQ2.js";
26
26
  import "./chunk-GDKLH7ZY.js";
@@ -20,7 +20,7 @@ import {
20
20
  saveSessionDiskMeta,
21
21
  setActivePage,
22
22
  touchSession
23
- } from "./chunk-HRTXMFW4.js";
23
+ } from "./chunk-ISOSRTTV.js";
24
24
  import "./chunk-TNEN6VQ2.js";
25
25
  import "./chunk-GDKLH7ZY.js";
26
26
  import "./chunk-KFQGP6VL.js";
@@ -38,9 +38,23 @@ function filterRecording(inputPath, outputPath, excludeTypes) {
38
38
  return { originalCount, filteredCount, removed, percentage };
39
39
  }
40
40
  function parseExcludeTypes(args) {
41
- for (const arg of args) {
41
+ for (let i = 0; i < args.length; i++) {
42
+ const arg = args[i];
42
43
  if (arg.startsWith("--exclude-types=")) {
43
- return arg.replace("--exclude-types=", "").split(",");
44
+ return arg.replace("--exclude-types=", "").split(",").map((s) => s.trim());
45
+ }
46
+ if (arg === "--exclude-types" && args[i + 1]) {
47
+ return args[i + 1].split(",").map((s) => s.trim());
48
+ }
49
+ if (arg.startsWith("--exclude=")) {
50
+ return arg.replace("--exclude=", "").split(",").map((s) => s.trim());
51
+ }
52
+ if (arg === "--exclude" && args[i + 1]) {
53
+ const types = [];
54
+ for (let j = i + 1; j < args.length && !args[j].startsWith("-"); j++) {
55
+ types.push(...args[j].split(",").map((s) => s.trim()));
56
+ }
57
+ if (types.length > 0) return types;
44
58
  }
45
59
  }
46
60
  return void 0;
@@ -1538,7 +1538,7 @@ async function getCDPTargets(cdpEndpoint) {
1538
1538
  }
1539
1539
  async function findTargetPage(cdpEndpoint, target) {
1540
1540
  const targets = await getCDPTargets(cdpEndpoint);
1541
- const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://"));
1541
+ const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://") && !t.url.startsWith("chrome-untrusted://") && !t.url.startsWith("chrome-error://"));
1542
1542
  const byId = pages.find((t) => t.id === target);
1543
1543
  if (byId) return { pageId: byId.id, wsUrl: byId.webSocketDebuggerUrl, title: byId.title, url: byId.url };
1544
1544
  const lowerTarget = target.toLowerCase();
@@ -4284,7 +4284,7 @@ async function getCDPTargets2(cdpEndpoint) {
4284
4284
  }
4285
4285
  async function findTargetPage(cdpEndpoint, target) {
4286
4286
  const targets = await getCDPTargets2(cdpEndpoint);
4287
- const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://"));
4287
+ const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://") && !t.url.startsWith("chrome-untrusted://") && !t.url.startsWith("chrome-error://"));
4288
4288
  const byId = pages.find((t) => t.id === target);
4289
4289
  if (byId) return { pageId: byId.id, wsUrl: byId.webSocketDebuggerUrl, title: byId.title, url: byId.url };
4290
4290
  const lowerTarget = target.toLowerCase();
@@ -173,7 +173,7 @@ async function getCDPTargets(cdpEndpoint) {
173
173
  }
174
174
  async function findTargetPage(cdpEndpoint, target) {
175
175
  const targets = await getCDPTargets(cdpEndpoint);
176
- const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://"));
176
+ const pages = targets.filter((t) => t.url && !t.url.startsWith("about:blank") && !t.url.startsWith("chrome://") && !t.url.startsWith("chrome-untrusted://") && !t.url.startsWith("chrome-error://"));
177
177
  const byId = pages.find((t) => t.id === target);
178
178
  if (byId) return { pageId: byId.id, wsUrl: byId.webSocketDebuggerUrl, title: byId.title, url: byId.url };
179
179
  const lowerTarget = target.toLowerCase();
package/dist/cli.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  resolveLaunchOpts,
26
26
  saveSessionDiskMeta,
27
27
  setActivePage
28
- } from "./chunk-HRTXMFW4.js";
28
+ } from "./chunk-ISOSRTTV.js";
29
29
  import "./chunk-TNEN6VQ2.js";
30
30
  import {
31
31
  forwardCommandLog,
@@ -337,7 +337,8 @@ var gotoCommand = registerCommand({
337
337
  scope: "page",
338
338
  parameters: z.object({
339
339
  url: z.string(),
340
- waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional()
340
+ waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional(),
341
+ timeout: z.number().optional()
341
342
  }),
342
343
  result: z.object({
343
344
  url: z.string(),
@@ -355,7 +356,8 @@ var gotoCommand = registerCommand({
355
356
  }
356
357
  }
357
358
  const response = await ctx.page.goto(url, {
358
- waitUntil: p.waitUntil || "domcontentloaded"
359
+ waitUntil: p.waitUntil || "domcontentloaded",
360
+ ...p.timeout ? { timeout: p.timeout } : {}
359
361
  });
360
362
  const ssr = await detectSsr(ctx.page);
361
363
  return ok({ url, status: response?.status(), ...ssr ? { ssr } : {} });
@@ -6967,7 +6969,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6967
6969
  }
6968
6970
  let targetPageOverride = null;
6969
6971
  if (_target && extraOpts?.cdpEndpoint) {
6970
- const { findTargetPage } = await import("./browser-AN6MKGOD.js");
6972
+ const { findTargetPage } = await import("./browser-CFHOD5GY.js");
6971
6973
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6972
6974
  if (!targetPageOverride) {
6973
6975
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -9070,7 +9072,7 @@ var createBuiltin = {
9070
9072
  );
9071
9073
  process.exit(1);
9072
9074
  }
9073
- const targetDir = path2.join(ctx.cwd, projectName);
9075
+ const targetDir = path2.isAbsolute(projectName) ? projectName : path2.join(ctx.cwd, projectName);
9074
9076
  if (fs2.existsSync(targetDir) && !options["force"]) {
9075
9077
  console.error(`Directory "${projectName}" already exists. Use --force to overwrite.`);
9076
9078
  process.exit(1);
@@ -9593,7 +9595,8 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9593
9595
  cmdName = "goto";
9594
9596
  params = {
9595
9597
  url: /^https?:\/\//i.test(args[0]) || /^wss?:\/\//i.test(args[0]) ? args[0] : "https://" + args[0],
9596
- waitUntil: options.waitUntil
9598
+ waitUntil: options.waitUntil,
9599
+ ...options.timeout ? { timeout: Number(options.timeout) } : {}
9597
9600
  };
9598
9601
  break;
9599
9602
  case "screenshot":
@@ -9843,6 +9846,14 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9843
9846
  outputResult(result.data, mode);
9844
9847
  }
9845
9848
  }
9849
+ const outputFile = options.output;
9850
+ if (outputFile && result.success && result.data) {
9851
+ const { writeFileSync: writeFileSync11 } = await import("fs");
9852
+ const content = typeof result.data === "string" ? result.data : result.data.content || result.data.text || JSON.stringify(result.data, null, 2);
9853
+ writeFileSync11(outputFile, content, "utf-8");
9854
+ console.log(`
9855
+ \u{1F4C4} Written to ${outputFile}`);
9856
+ }
9846
9857
  }
9847
9858
 
9848
9859
  // src/cli/session-routes.ts
@@ -10646,7 +10657,7 @@ async function handleFilter(args, _mode) {
10646
10657
  console.error("Usage: xbrowser filter <input.yaml> <output.yaml> [--exclude-types=type1,type2]");
10647
10658
  process.exit(1);
10648
10659
  }
10649
- const { filterRecording, parseExcludeTypes } = await import("./filter-KCFO4RSV.js");
10660
+ const { filterRecording, parseExcludeTypes } = await import("./filter-EDTFGLS5.js");
10650
10661
  const excludeTypes = parseExcludeTypes(args.slice(2));
10651
10662
  const result = filterRecording(filePath, outputPath, excludeTypes);
10652
10663
  console.log(`Filtered ${filePath} -> ${outputPath}`);
@@ -12272,13 +12283,13 @@ async function routeCommand(argvIn, stdinCommands) {
12272
12283
  handleConfig(cmdArgs, options);
12273
12284
  break;
12274
12285
  case "convert":
12275
- handleConvert(cmdArgs, mode);
12286
+ await handleConvert(cmdArgs, mode);
12276
12287
  break;
12277
12288
  case "extract":
12278
- handleExtract(cmdArgs, mode);
12289
+ await handleExtract(cmdArgs, mode);
12279
12290
  break;
12280
12291
  case "filter":
12281
- handleFilter(cmdArgs, mode);
12292
+ await handleFilter(cmdArgs, mode);
12282
12293
  break;
12283
12294
  case "run":
12284
12295
  if (!cmdArgs[0]) {
@@ -12727,7 +12738,7 @@ async function main() {
12727
12738
  const command = process.argv[2];
12728
12739
  const isLongRunning = command === "preview" || command === "serve";
12729
12740
  if (!isLongRunning) {
12730
- const { ensureProcessCanExit } = await import("./browser-AN6MKGOD.js");
12741
+ const { ensureProcessCanExit } = await import("./browser-CFHOD5GY.js");
12731
12742
  await ensureProcessCanExit().catch(() => {
12732
12743
  });
12733
12744
  process.exit(exitCode);
@@ -21,7 +21,7 @@ import {
21
21
  resolveLaunchOpts,
22
22
  saveSessionDiskMeta,
23
23
  setActivePage
24
- } from "./chunk-JUNEBEGF.js";
24
+ } from "./chunk-GOKTOYWM.js";
25
25
  import "./chunk-IX4JY6OO.js";
26
26
  import "./chunk-TNEN6VQ2.js";
27
27
  import {
@@ -295,7 +295,8 @@ var gotoCommand = registerCommand({
295
295
  scope: "page",
296
296
  parameters: z.object({
297
297
  url: z.string(),
298
- waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional()
298
+ waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional(),
299
+ timeout: z.number().optional()
299
300
  }),
300
301
  result: z.object({
301
302
  url: z.string(),
@@ -313,7 +314,8 @@ var gotoCommand = registerCommand({
313
314
  }
314
315
  }
315
316
  const response = await ctx.page.goto(url, {
316
- waitUntil: p.waitUntil || "domcontentloaded"
317
+ waitUntil: p.waitUntil || "domcontentloaded",
318
+ ...p.timeout ? { timeout: p.timeout } : {}
317
319
  });
318
320
  const ssr = await detectSsr(ctx.page);
319
321
  return ok({ url, status: response?.status(), ...ssr ? { ssr } : {} });
@@ -6925,7 +6927,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
6925
6927
  }
6926
6928
  let targetPageOverride = null;
6927
6929
  if (_target && extraOpts?.cdpEndpoint) {
6928
- const { findTargetPage } = await import("./browser-MUPES4UY.js");
6930
+ const { findTargetPage } = await import("./browser-BX4HZOUT.js");
6929
6931
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
6930
6932
  if (!targetPageOverride) {
6931
6933
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  filterRecording,
3
3
  parseExcludeTypes
4
- } from "./chunk-OPRXFZVE.js";
4
+ } from "./chunk-AT4PHAJY.js";
5
5
  import "./chunk-KFQGP6VL.js";
6
6
  export {
7
7
  filterRecording,
@@ -40,9 +40,23 @@ function filterRecording(inputPath, outputPath, excludeTypes) {
40
40
  return { originalCount, filteredCount, removed, percentage };
41
41
  }
42
42
  function parseExcludeTypes(args) {
43
- for (const arg of args) {
43
+ for (let i = 0; i < args.length; i++) {
44
+ const arg = args[i];
44
45
  if (arg.startsWith("--exclude-types=")) {
45
- return arg.replace("--exclude-types=", "").split(",");
46
+ return arg.replace("--exclude-types=", "").split(",").map((s) => s.trim());
47
+ }
48
+ if (arg === "--exclude-types" && args[i + 1]) {
49
+ return args[i + 1].split(",").map((s) => s.trim());
50
+ }
51
+ if (arg.startsWith("--exclude=")) {
52
+ return arg.replace("--exclude=", "").split(",").map((s) => s.trim());
53
+ }
54
+ if (arg === "--exclude" && args[i + 1]) {
55
+ const types = [];
56
+ for (let j = i + 1; j < args.length && !args[j].startsWith("-"); j++) {
57
+ types.push(...args[j].split(",").map((s) => s.trim()));
58
+ }
59
+ if (types.length > 0) return types;
46
60
  }
47
61
  }
48
62
  return void 0;
package/dist/index.js CHANGED
@@ -53,7 +53,7 @@ import {
53
53
  import {
54
54
  filterRecording,
55
55
  parseExcludeTypes
56
- } from "./chunk-OPRXFZVE.js";
56
+ } from "./chunk-AT4PHAJY.js";
57
57
  import {
58
58
  SessionRecorder
59
59
  } from "./chunk-ACFE6PKF.js";
@@ -81,7 +81,7 @@ import {
81
81
  resolveLaunchOpts,
82
82
  saveSessionDiskMeta,
83
83
  setActivePage
84
- } from "./chunk-EUHVZVVL.js";
84
+ } from "./chunk-MWBVZWXA.js";
85
85
  import "./chunk-IX4JY6OO.js";
86
86
  import "./chunk-TNEN6VQ2.js";
87
87
  import {
@@ -377,7 +377,8 @@ var gotoCommand = registerCommand({
377
377
  scope: "page",
378
378
  parameters: z.object({
379
379
  url: z.string(),
380
- waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional()
380
+ waitUntil: z.enum(["load", "domcontentloaded", "networkidle"]).optional(),
381
+ timeout: z.number().optional()
381
382
  }),
382
383
  result: z.object({
383
384
  url: z.string(),
@@ -395,7 +396,8 @@ var gotoCommand = registerCommand({
395
396
  }
396
397
  }
397
398
  const response = await ctx.page.goto(url, {
398
- waitUntil: p.waitUntil || "domcontentloaded"
399
+ waitUntil: p.waitUntil || "domcontentloaded",
400
+ ...p.timeout ? { timeout: p.timeout } : {}
399
401
  });
400
402
  const ssr = await detectSsr(ctx.page);
401
403
  return ok({ url, status: response?.status(), ...ssr ? { ssr } : {} });
@@ -7287,7 +7289,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
7287
7289
  }
7288
7290
  let targetPageOverride = null;
7289
7291
  if (_target && extraOpts?.cdpEndpoint) {
7290
- const { findTargetPage } = await import("./browser-6QN42A4K.js");
7292
+ const { findTargetPage } = await import("./browser-5FR3B57B.js");
7291
7293
  targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
7292
7294
  if (!targetPageOverride) {
7293
7295
  return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
@@ -9405,7 +9407,7 @@ var createBuiltin = {
9405
9407
  );
9406
9408
  process.exit(1);
9407
9409
  }
9408
- const targetDir = path2.join(ctx.cwd, projectName);
9410
+ const targetDir = path2.isAbsolute(projectName) ? projectName : path2.join(ctx.cwd, projectName);
9409
9411
  if (fs2.existsSync(targetDir) && !options["force"]) {
9410
9412
  console.error(`Directory "${projectName}" already exists. Use --force to overwrite.`);
9411
9413
  process.exit(1);
@@ -9933,7 +9935,8 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
9933
9935
  cmdName = "goto";
9934
9936
  params = {
9935
9937
  url: /^https?:\/\//i.test(args[0]) || /^wss?:\/\//i.test(args[0]) ? args[0] : "https://" + args[0],
9936
- waitUntil: options.waitUntil
9938
+ waitUntil: options.waitUntil,
9939
+ ...options.timeout ? { timeout: Number(options.timeout) } : {}
9937
9940
  };
9938
9941
  break;
9939
9942
  case "screenshot":
@@ -10183,6 +10186,14 @@ async function handleBrowserCommand(command, args, options, sessionName, mode, c
10183
10186
  outputResult(result.data, mode);
10184
10187
  }
10185
10188
  }
10189
+ const outputFile = options.output;
10190
+ if (outputFile && result.success && result.data) {
10191
+ const { writeFileSync: writeFileSync12 } = await import("fs");
10192
+ const content = typeof result.data === "string" ? result.data : result.data.content || result.data.text || JSON.stringify(result.data, null, 2);
10193
+ writeFileSync12(outputFile, content, "utf-8");
10194
+ console.log(`
10195
+ \u{1F4C4} Written to ${outputFile}`);
10196
+ }
10186
10197
  }
10187
10198
 
10188
10199
  // src/cli/session-routes.ts
@@ -10986,7 +10997,7 @@ async function handleFilter(args, _mode) {
10986
10997
  console.error("Usage: xbrowser filter <input.yaml> <output.yaml> [--exclude-types=type1,type2]");
10987
10998
  process.exit(1);
10988
10999
  }
10989
- const { filterRecording: filterRecording2, parseExcludeTypes: parseExcludeTypes2 } = await import("./filter-T7DSZ2X7.js");
11000
+ const { filterRecording: filterRecording2, parseExcludeTypes: parseExcludeTypes2 } = await import("./filter-3JQWBM5F.js");
10990
11001
  const excludeTypes = parseExcludeTypes2(args.slice(2));
10991
11002
  const result = filterRecording2(filePath, outputPath, excludeTypes);
10992
11003
  console.log(`Filtered ${filePath} -> ${outputPath}`);
@@ -12612,13 +12623,13 @@ async function routeCommand(argvIn, stdinCommands) {
12612
12623
  handleConfig(cmdArgs, options);
12613
12624
  break;
12614
12625
  case "convert":
12615
- handleConvert(cmdArgs, mode);
12626
+ await handleConvert(cmdArgs, mode);
12616
12627
  break;
12617
12628
  case "extract":
12618
- handleExtract(cmdArgs, mode);
12629
+ await handleExtract(cmdArgs, mode);
12619
12630
  break;
12620
12631
  case "filter":
12621
- handleFilter(cmdArgs, mode);
12632
+ await handleFilter(cmdArgs, mode);
12622
12633
  break;
12623
12634
  case "run":
12624
12635
  if (!cmdArgs[0]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xbrowser/cli",
3
- "version": "1.0.9",
3
+ "version": "1.1.1",
4
4
  "description": "Browser automation CLI for web scraping, headless browsing, SEO analysis, and AI agent workflows. A command-line alternative to Playwright, Puppeteer, and Selenium.",
5
5
  "type": "module",
6
6
  "bin": {