@vercel/next-browser 0.4.1 → 0.5.0

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.
package/dist/cli.js CHANGED
@@ -3,6 +3,7 @@ import { readFileSync, writeFileSync } from "node:fs";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
  import { send } from "./client.js";
6
+ import { parseCookies } from "./cookies.js";
6
7
  const args = process.argv.slice(2);
7
8
  const cmd = args[0];
8
9
  const arg = args[1];
@@ -17,18 +18,29 @@ if (cmd === "--version" || cmd === "-v") {
17
18
  }
18
19
  if (cmd === "open") {
19
20
  if (!arg) {
20
- console.error("usage: next-browser open <url> [--cookies-json <file>]");
21
+ console.error("usage: next-browser open <url> [--cookies <file>]");
21
22
  process.exit(1);
22
23
  }
23
24
  const url = /^https?:\/\//.test(arg) ? arg : `http://${arg}`;
24
- const cookieIdx = args.indexOf("--cookies-json");
25
+ const cookieIdx = (() => {
26
+ const i = args.indexOf("--cookies");
27
+ if (i >= 0)
28
+ return i;
29
+ return args.indexOf("--cookies-json"); // back-compat alias
30
+ })();
25
31
  const cookieFile = cookieIdx >= 0 ? args[cookieIdx + 1] : undefined;
26
32
  if (cookieFile) {
27
33
  const res = await send("open");
28
34
  if (!res.ok)
29
35
  exit(res, "");
30
- const raw = readFileSync(cookieFile, "utf-8");
31
- const cookies = JSON.parse(raw);
36
+ let cookies;
37
+ try {
38
+ cookies = parseCookies(readFileSync(cookieFile, "utf-8"));
39
+ }
40
+ catch (e) {
41
+ console.error(`cookies: ${e.message}`);
42
+ process.exit(1);
43
+ }
32
44
  const domain = new URL(url).hostname;
33
45
  const cRes = await send("cookies", { cookies, domain });
34
46
  if (!cRes.ok)
@@ -428,7 +440,7 @@ function pick(items) {
428
440
  function printUsage() {
429
441
  console.error("usage: next-browser <command> [args]\n" +
430
442
  "\n" +
431
- " open <url> [--cookies-json <file>] launch browser and navigate\n" +
443
+ " open <url> [--cookies <file>] launch browser and navigate\n" +
432
444
  " close close browser and daemon\n" +
433
445
  "\n" +
434
446
  " goto <url> full-page navigation (new document load)\n" +
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Parse cookie input in one of three formats, auto-detected from the first
3
+ * non-whitespace character:
4
+ *
5
+ * 1. JSON array — Playwright-style `[{"name": "x", "value": "y"}, ...]`.
6
+ * 2. cURL command — as produced by DevTools → Network → Copy as cURL.
7
+ * The Cookie header is extracted from the `-H 'cookie: …'` argument.
8
+ * 3. Bare cookie header — `name=v; name=v; ...` (e.g. the value of the
9
+ * Cookie row in DevTools → Network → Request Headers).
10
+ *
11
+ * The parser deliberately never echoes the secret value back in an error
12
+ * message — error text mentions the format, not the contents.
13
+ */
14
+ export function parseCookies(raw) {
15
+ const trimmed = raw.trim();
16
+ if (!trimmed)
17
+ throw new Error("cookies file is empty");
18
+ if (trimmed[0] === "[") {
19
+ const arr = JSON.parse(trimmed);
20
+ if (!Array.isArray(arr))
21
+ throw new Error("cookies JSON must be an array");
22
+ return arr.map((c, i) => {
23
+ if (!c ||
24
+ typeof c.name !== "string" ||
25
+ typeof c.value !== "string") {
26
+ throw new Error(`cookies[${i}] must have string name and value`);
27
+ }
28
+ const { name, value } = c;
29
+ return { name, value };
30
+ });
31
+ }
32
+ if (/^curl[\s'"]/i.test(trimmed)) {
33
+ const header = extractCookieHeaderFromCurl(trimmed);
34
+ if (!header) {
35
+ throw new Error("no Cookie header found in this cURL — right-click an authenticated request in DevTools → Network → Copy → Copy as cURL");
36
+ }
37
+ return parseCookieHeader(header);
38
+ }
39
+ return parseCookieHeader(trimmed);
40
+ }
41
+ function extractCookieHeaderFromCurl(curl) {
42
+ // Strip bash (`\`) and cmd (`^`) line continuations so the -H arg is on one line.
43
+ const joined = curl.replace(/\\\r?\n\s*/g, " ").replace(/\^\r?\n\s*/g, " ");
44
+ // -H 'cookie: …' (bash) or -H "cookie: …" (cmd). Chrome/Firefox use one
45
+ // or the other depending on which Copy-as-cURL variant the user picked.
46
+ const m = joined.match(/-H\s+(['"])\s*cookie\s*:\s*([\s\S]*?)\1/i);
47
+ return m ? m[2] : null;
48
+ }
49
+ function parseCookieHeader(header) {
50
+ const pairs = [];
51
+ for (const piece of header.split(/;\s*/)) {
52
+ const eq = piece.indexOf("=");
53
+ if (eq < 0)
54
+ continue;
55
+ const name = piece.slice(0, eq).trim();
56
+ const value = piece.slice(eq + 1).trim();
57
+ if (name)
58
+ pairs.push({ name, value });
59
+ }
60
+ if (pairs.length === 0)
61
+ throw new Error("no cookies found in input");
62
+ return pairs;
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/next-browser",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Headed Playwright browser with React DevTools pre-loaded",
5
5
  "license": "MIT",
6
6
  "repository": {