@presto1314w/vite-devtools-browser 0.1.3 → 0.1.4

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
@@ -1,165 +1,176 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFileSync } from "node:fs";
3
3
  import { send } from "./client.js";
4
- const args = process.argv.slice(2);
5
- const cmd = args[0];
6
- const arg = args[1];
7
- if (cmd === "--help" || cmd === "-h" || !cmd) {
8
- printUsage();
9
- process.exit(0);
10
- }
11
- if (cmd === "open") {
12
- if (!arg) {
13
- console.error("usage: vite-browser open <url> [--cookies-json <file>]");
14
- process.exit(1);
15
- }
16
- const url = normalizeUrl(arg);
17
- const cookieIdx = args.indexOf("--cookies-json");
18
- const cookieFile = cookieIdx >= 0 ? args[cookieIdx + 1] : undefined;
19
- if (cookieFile) {
20
- const res = await send("open");
21
- if (!res.ok)
22
- exit(res, "");
23
- const raw = readFileSync(cookieFile, "utf-8");
24
- const cookies = JSON.parse(raw);
25
- const domain = new URL(url).hostname;
26
- const cRes = await send("cookies", { cookies, domain });
27
- if (!cRes.ok)
28
- exit(cRes, "");
29
- await send("goto", { url });
30
- exit(res, `opened -> ${url} (${cookies.length} cookies for ${domain})`);
31
- }
32
- const res = await send("open", { url });
33
- exit(res, `opened -> ${url}`);
34
- }
35
- if (cmd === "close") {
36
- const res = await send("close");
37
- exit(res, "closed");
4
+ export function normalizeUrl(value) {
5
+ if (value.includes("://"))
6
+ return value;
7
+ return `http://${value}`;
38
8
  }
39
- if (cmd === "goto") {
40
- if (!arg) {
41
- console.error("usage: vite-browser goto <url>");
42
- process.exit(1);
9
+ export function parseNumberFlag(args, name, fallback) {
10
+ const idx = args.indexOf(name);
11
+ if (idx < 0)
12
+ return fallback;
13
+ return Number.parseInt(args[idx + 1] ?? String(fallback), 10);
14
+ }
15
+ export async function runCli(argv, io) {
16
+ const args = argv.slice(2);
17
+ const cmd = args[0];
18
+ const arg = args[1];
19
+ if (cmd === "--help" || cmd === "-h" || !cmd) {
20
+ io.stdout(printUsage());
21
+ io.exit(0);
43
22
  }
44
- const res = await send("goto", { url: normalizeUrl(arg) });
45
- exit(res, res.ok ? `-> ${res.data}` : "");
46
- }
47
- if (cmd === "back") {
48
- const res = await send("back");
49
- exit(res, "back");
50
- }
51
- if (cmd === "reload") {
52
- const res = await send("reload");
53
- exit(res, res.ok ? `reloaded -> ${res.data}` : "");
54
- }
55
- if (cmd === "detect") {
56
- const res = await send("detect");
57
- exit(res, res.ok && res.data ? String(res.data) : "");
58
- }
59
- if (cmd === "vue" && arg === "tree") {
60
- const id = args[2];
61
- const res = await send("vue-tree", { id });
62
- exit(res, res.ok && res.data ? String(res.data) : "");
63
- }
64
- if (cmd === "vue" && arg === "pinia") {
65
- const store = args[2];
66
- const res = await send("vue-pinia", { store });
67
- exit(res, res.ok && res.data ? String(res.data) : "");
68
- }
69
- if (cmd === "vue" && arg === "router") {
70
- const res = await send("vue-router");
71
- exit(res, res.ok && res.data ? String(res.data) : "");
72
- }
73
- if (cmd === "react" && arg === "tree") {
74
- const id = args[2];
75
- const res = await send("react-tree", { id });
76
- exit(res, res.ok && res.data ? String(res.data) : "");
77
- }
78
- if (cmd === "svelte" && arg === "tree") {
79
- const id = args[2];
80
- const res = await send("svelte-tree", { id });
81
- exit(res, res.ok && res.data ? String(res.data) : "");
82
- }
83
- if (cmd === "vite" && arg === "restart") {
84
- const res = await send("vite-restart");
85
- exit(res, res.ok && res.data ? String(res.data) : "restarted");
86
- }
87
- if (cmd === "vite" && arg === "hmr") {
88
- const sub = args[2];
89
- if (sub === "clear") {
90
- const res = await send("vite-hmr", { mode: "clear" });
91
- exit(res, res.ok && res.data ? String(res.data) : "cleared HMR trace");
92
- }
93
- if (sub === "trace") {
94
- const limitIdx = args.indexOf("--limit");
95
- const limit = limitIdx >= 0 ? Number.parseInt(args[limitIdx + 1] ?? "20", 10) : 20;
96
- const res = await send("vite-hmr", { mode: "trace", limit });
97
- exit(res, res.ok && res.data ? String(res.data) : "");
98
- }
99
- const res = await send("vite-hmr", { mode: "summary", limit: 20 });
100
- exit(res, res.ok && res.data ? String(res.data) : "");
101
- }
102
- if (cmd === "vite" && arg === "runtime") {
103
- const res = await send("vite-runtime");
104
- exit(res, res.ok && res.data ? String(res.data) : "");
105
- }
106
- if (cmd === "vite" && arg === "module-graph") {
107
- const sub = args[2];
108
- const filterIdx = args.indexOf("--filter");
109
- const limitIdx = args.indexOf("--limit");
110
- const filter = filterIdx >= 0 ? args[filterIdx + 1] : undefined;
111
- const limit = limitIdx >= 0 ? Number.parseInt(args[limitIdx + 1] ?? "200", 10) : 200;
112
- if (sub === "clear") {
113
- const res = await send("vite-module-graph", { mode: "clear" });
114
- exit(res, res.ok && res.data ? String(res.data) : "cleared module-graph baseline");
115
- }
116
- if (sub === "trace") {
117
- const res = await send("vite-module-graph", { mode: "trace", filter, limit });
118
- exit(res, res.ok && res.data ? String(res.data) : "");
119
- }
120
- const res = await send("vite-module-graph", { mode: "snapshot", filter, limit });
121
- exit(res, res.ok && res.data ? String(res.data) : "");
122
- }
123
- if (cmd === "errors") {
124
- const mapped = args.includes("--mapped");
125
- const inlineSource = args.includes("--inline-source");
126
- const res = await send("errors", { mapped, inlineSource });
127
- exit(res, res.ok && res.data ? String(res.data) : "no errors");
128
- }
129
- if (cmd === "logs") {
130
- const res = await send("logs");
131
- exit(res, res.ok && res.data ? String(res.data) : "");
132
- }
133
- if (cmd === "screenshot") {
134
- const res = await send("screenshot");
135
- exit(res, res.ok && res.data ? String(res.data) : "");
136
- }
137
- if (cmd === "eval") {
138
- if (!arg) {
139
- console.error("usage: vite-browser eval <script>");
140
- process.exit(1);
23
+ if (cmd === "open") {
24
+ if (!arg) {
25
+ io.stderr("usage: vite-browser open <url> [--cookies-json <file>]");
26
+ io.exit(1);
27
+ }
28
+ const url = normalizeUrl(arg);
29
+ const cookieIdx = args.indexOf("--cookies-json");
30
+ const cookieFile = cookieIdx >= 0 ? args[cookieIdx + 1] : undefined;
31
+ if (cookieFile) {
32
+ const res = await io.send("open");
33
+ if (!res.ok)
34
+ exit(io, res, "");
35
+ const raw = io.readFile(cookieFile, "utf-8");
36
+ const cookies = JSON.parse(raw);
37
+ const domain = new URL(url).hostname;
38
+ const cRes = await io.send("cookies", { cookies, domain });
39
+ if (!cRes.ok)
40
+ exit(io, cRes, "");
41
+ await io.send("goto", { url });
42
+ exit(io, res, `opened -> ${url} (${cookies.length} cookies for ${domain})`);
43
+ }
44
+ const res = await io.send("open", { url });
45
+ exit(io, res, `opened -> ${url}`);
141
46
  }
142
- const res = await send("eval", { script: arg });
143
- exit(res, res.ok && res.data ? String(res.data) : "");
144
- }
145
- if (cmd === "network") {
146
- const idx = arg ? parseInt(arg, 10) : undefined;
147
- const res = await send("network", { idx });
148
- exit(res, res.ok && res.data ? String(res.data) : "");
47
+ if (cmd === "close") {
48
+ const res = await io.send("close");
49
+ exit(io, res, "closed");
50
+ }
51
+ if (cmd === "goto") {
52
+ if (!arg) {
53
+ io.stderr("usage: vite-browser goto <url>");
54
+ io.exit(1);
55
+ }
56
+ const res = await io.send("goto", { url: normalizeUrl(arg) });
57
+ exit(io, res, res.ok ? `-> ${res.data}` : "");
58
+ }
59
+ if (cmd === "back") {
60
+ const res = await io.send("back");
61
+ exit(io, res, "back");
62
+ }
63
+ if (cmd === "reload") {
64
+ const res = await io.send("reload");
65
+ exit(io, res, res.ok ? `reloaded -> ${res.data}` : "");
66
+ }
67
+ if (cmd === "detect") {
68
+ const res = await io.send("detect");
69
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
70
+ }
71
+ if (cmd === "vue" && arg === "tree") {
72
+ const id = args[2];
73
+ const res = await io.send("vue-tree", { id });
74
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
75
+ }
76
+ if (cmd === "vue" && arg === "pinia") {
77
+ const store = args[2];
78
+ const res = await io.send("vue-pinia", { store });
79
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
80
+ }
81
+ if (cmd === "vue" && arg === "router") {
82
+ const res = await io.send("vue-router");
83
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
84
+ }
85
+ if (cmd === "react" && arg === "tree") {
86
+ const id = args[2];
87
+ const res = await io.send("react-tree", { id });
88
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
89
+ }
90
+ if (cmd === "svelte" && arg === "tree") {
91
+ const id = args[2];
92
+ const res = await io.send("svelte-tree", { id });
93
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
94
+ }
95
+ if (cmd === "vite" && arg === "restart") {
96
+ const res = await io.send("vite-restart");
97
+ exit(io, res, res.ok && res.data ? String(res.data) : "restarted");
98
+ }
99
+ if (cmd === "vite" && arg === "hmr") {
100
+ const sub = args[2];
101
+ if (sub === "clear") {
102
+ const res = await io.send("vite-hmr", { mode: "clear" });
103
+ exit(io, res, res.ok && res.data ? String(res.data) : "cleared HMR trace");
104
+ }
105
+ if (sub === "trace") {
106
+ const limit = parseNumberFlag(args, "--limit", 20);
107
+ const res = await io.send("vite-hmr", { mode: "trace", limit });
108
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
109
+ }
110
+ const res = await io.send("vite-hmr", { mode: "summary", limit: 20 });
111
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
112
+ }
113
+ if (cmd === "vite" && arg === "runtime") {
114
+ const res = await io.send("vite-runtime");
115
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
116
+ }
117
+ if (cmd === "vite" && arg === "module-graph") {
118
+ const sub = args[2];
119
+ const filterIdx = args.indexOf("--filter");
120
+ const filter = filterIdx >= 0 ? args[filterIdx + 1] : undefined;
121
+ const limit = parseNumberFlag(args, "--limit", 200);
122
+ if (sub === "clear") {
123
+ const res = await io.send("vite-module-graph", { mode: "clear" });
124
+ exit(io, res, res.ok && res.data ? String(res.data) : "cleared module-graph baseline");
125
+ }
126
+ if (sub === "trace") {
127
+ const res = await io.send("vite-module-graph", { mode: "trace", filter, limit });
128
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
129
+ }
130
+ const res = await io.send("vite-module-graph", { mode: "snapshot", filter, limit });
131
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
132
+ }
133
+ if (cmd === "errors") {
134
+ const mapped = args.includes("--mapped");
135
+ const inlineSource = args.includes("--inline-source");
136
+ const res = await io.send("errors", { mapped, inlineSource });
137
+ exit(io, res, res.ok && res.data ? String(res.data) : "no errors");
138
+ }
139
+ if (cmd === "logs") {
140
+ const res = await io.send("logs");
141
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
142
+ }
143
+ if (cmd === "screenshot") {
144
+ const res = await io.send("screenshot");
145
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
146
+ }
147
+ if (cmd === "eval") {
148
+ if (!arg) {
149
+ io.stderr("usage: vite-browser eval <script>");
150
+ io.exit(1);
151
+ }
152
+ const res = await io.send("eval", { script: arg });
153
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
154
+ }
155
+ if (cmd === "network") {
156
+ const idx = arg ? parseInt(arg, 10) : undefined;
157
+ const res = await io.send("network", { idx });
158
+ exit(io, res, res.ok && res.data ? String(res.data) : "");
159
+ }
160
+ io.stderr(`unknown command: ${cmd}`);
161
+ io.exit(1);
149
162
  }
150
- console.error(`unknown command: ${cmd}`);
151
- process.exit(1);
152
- function exit(res, msg) {
163
+ export function exit(io, res, msg) {
153
164
  if (!res.ok) {
154
- console.error(res.error || "error");
155
- process.exit(1);
165
+ io.stderr(res.error || "error");
166
+ io.exit(1);
156
167
  }
157
168
  if (msg)
158
- console.log(msg);
159
- process.exit(0);
169
+ io.stdout(msg);
170
+ io.exit(0);
160
171
  }
161
- function printUsage() {
162
- console.log(`
172
+ export function printUsage() {
173
+ return `
163
174
  vite-browser - Programmatic access to Vue/React/Svelte DevTools and Vite dev server
164
175
 
165
176
  USAGE
@@ -209,10 +220,14 @@ UTILITIES
209
220
 
210
221
  OPTIONS
211
222
  -h, --help Show this help message
212
- `);
213
- }
214
- function normalizeUrl(value) {
215
- if (value.includes("://"))
216
- return value;
217
- return `http://${value}`;
223
+ `;
224
+ }
225
+ if (process.argv[1] && import.meta.url.endsWith(process.argv[1].replaceAll("\\", "/"))) {
226
+ await runCli(process.argv, {
227
+ send,
228
+ readFile: readFileSync,
229
+ stdout: (text) => console.log(text),
230
+ stderr: (text) => console.error(text),
231
+ exit: (code) => process.exit(code),
232
+ });
218
233
  }
package/dist/client.d.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import { type Socket } from "node:net";
2
+ import { readFileSync, existsSync, rmSync } from "node:fs";
3
+ import { spawn } from "node:child_process";
4
+ import { setTimeout as sleep } from "node:timers/promises";
1
5
  export type Response = {
2
6
  ok: true;
3
7
  data?: unknown;
@@ -5,4 +9,24 @@ export type Response = {
5
9
  ok: false;
6
10
  error: string;
7
11
  };
12
+ export type ClientDeps = {
13
+ socketPath: string;
14
+ pidFile: string;
15
+ existsSync: typeof existsSync;
16
+ readFileSync: typeof readFileSync;
17
+ rmSync: typeof rmSync;
18
+ processKill: typeof process.kill;
19
+ spawn: typeof spawn;
20
+ connect: () => Promise<Socket>;
21
+ sleep: typeof sleep;
22
+ daemonPath: string;
23
+ };
24
+ export declare function createClientDeps(): ClientDeps;
8
25
  export declare function send(action: string, payload?: Record<string, unknown>): Promise<Response>;
26
+ export declare function ensureDaemon(deps: ClientDeps): Promise<void>;
27
+ export declare function daemonAlive(deps: Pick<ClientDeps, "existsSync" | "pidFile" | "readFileSync" | "processKill" | "rmSync" | "socketPath">): boolean;
28
+ export declare function connect(): Promise<Socket>;
29
+ export declare function readLine(socket: Pick<Socket, "on">): Promise<string>;
30
+ export declare function ok(s: Pick<Socket, "destroy">): boolean;
31
+ export declare function no(): boolean;
32
+ export declare function removeSocketFile(path: string, removeFile?: typeof rmSync): void;
package/dist/client.js CHANGED
@@ -4,54 +4,69 @@ import { spawn } from "node:child_process";
4
4
  import { setTimeout as sleep } from "node:timers/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { socketPath, pidFile } from "./paths.js";
7
+ export function createClientDeps() {
8
+ const ext = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
9
+ const daemonPath = fileURLToPath(new URL(`./daemon${ext}`, import.meta.url));
10
+ return {
11
+ socketPath,
12
+ pidFile,
13
+ existsSync,
14
+ readFileSync,
15
+ rmSync,
16
+ processKill: process.kill.bind(process),
17
+ spawn,
18
+ connect,
19
+ sleep,
20
+ daemonPath,
21
+ };
22
+ }
7
23
  export async function send(action, payload = {}) {
8
- await ensureDaemon();
9
- const socket = await connect();
24
+ const deps = createClientDeps();
25
+ await ensureDaemon(deps);
26
+ const socket = await deps.connect();
10
27
  const id = String(Date.now());
11
28
  socket.write(JSON.stringify({ id, action, ...payload }) + "\n");
12
29
  const line = await readLine(socket);
13
30
  socket.end();
14
31
  return JSON.parse(line);
15
32
  }
16
- async function ensureDaemon() {
17
- if (daemonAlive() && (await connect().then(ok, no)))
33
+ export async function ensureDaemon(deps) {
34
+ if (daemonAlive(deps) && (await deps.connect().then(ok, no)))
18
35
  return;
19
- const ext = import.meta.url.endsWith(".ts") ? ".ts" : ".js";
20
- const daemon = fileURLToPath(new URL(`./daemon${ext}`, import.meta.url));
21
- const child = spawn(process.execPath, [daemon], {
36
+ const child = deps.spawn(process.execPath, [deps.daemonPath], {
22
37
  detached: true,
23
38
  stdio: "ignore",
24
39
  });
25
40
  child.unref();
26
41
  for (let i = 0; i < 50; i++) {
27
- if (await connect().then(ok, no))
42
+ if (await deps.connect().then(ok, no))
28
43
  return;
29
- await sleep(100);
44
+ await deps.sleep(100);
30
45
  }
31
- throw new Error(`daemon failed to start (${socketPath})`);
46
+ throw new Error(`daemon failed to start (${deps.socketPath})`);
32
47
  }
33
- function daemonAlive() {
34
- if (!existsSync(pidFile))
48
+ export function daemonAlive(deps) {
49
+ if (!deps.existsSync(deps.pidFile))
35
50
  return false;
36
- const pid = Number(readFileSync(pidFile, "utf-8"));
51
+ const pid = Number(deps.readFileSync(deps.pidFile, "utf-8"));
37
52
  try {
38
- process.kill(pid, 0);
53
+ deps.processKill(pid, 0);
39
54
  return true;
40
55
  }
41
56
  catch {
42
- rmSync(pidFile, { force: true });
43
- removeSocketFile();
57
+ deps.rmSync(deps.pidFile, { force: true });
58
+ removeSocketFile(deps.socketPath, deps.rmSync);
44
59
  return false;
45
60
  }
46
61
  }
47
- function connect() {
62
+ export function connect() {
48
63
  return new Promise((resolve, reject) => {
49
64
  const socket = netConnect(socketPath);
50
65
  socket.once("connect", () => resolve(socket));
51
66
  socket.once("error", reject);
52
67
  });
53
68
  }
54
- function readLine(socket) {
69
+ export function readLine(socket) {
55
70
  return new Promise((resolve, reject) => {
56
71
  let buffer = "";
57
72
  socket.on("data", (chunk) => {
@@ -63,15 +78,15 @@ function readLine(socket) {
63
78
  socket.on("error", reject);
64
79
  });
65
80
  }
66
- function ok(s) {
81
+ export function ok(s) {
67
82
  s.destroy();
68
83
  return true;
69
84
  }
70
- function no() {
85
+ export function no() {
71
86
  return false;
72
87
  }
73
- function removeSocketFile() {
88
+ export function removeSocketFile(path, removeFile = rmSync) {
74
89
  if (process.platform === "win32")
75
90
  return;
76
- rmSync(socketPath, { force: true });
91
+ removeFile(path, { force: true });
77
92
  }
package/dist/daemon.d.ts CHANGED
@@ -1 +1,57 @@
1
- export {};
1
+ import type { Socket } from "node:net";
2
+ import * as browser from "./browser.js";
3
+ export type BrowserApi = typeof browser;
4
+ export type Cmd = {
5
+ action: string;
6
+ url?: string;
7
+ id?: string;
8
+ script?: string;
9
+ idx?: number;
10
+ mode?: "summary" | "trace" | "clear" | "snapshot";
11
+ limit?: number;
12
+ filter?: string;
13
+ mapped?: boolean;
14
+ inlineSource?: boolean;
15
+ cookies?: {
16
+ name: string;
17
+ value: string;
18
+ }[];
19
+ domain?: string;
20
+ store?: string;
21
+ };
22
+ export declare function cleanError(err: unknown): string;
23
+ export declare function createRunner(api?: BrowserApi): (cmd: Cmd) => Promise<{
24
+ ok: boolean;
25
+ data?: undefined;
26
+ error?: undefined;
27
+ } | {
28
+ ok: boolean;
29
+ data: number;
30
+ error?: undefined;
31
+ } | {
32
+ ok: boolean;
33
+ data: string;
34
+ error?: undefined;
35
+ } | {
36
+ ok: boolean;
37
+ error: string;
38
+ data?: undefined;
39
+ }>;
40
+ export declare function dispatchLine(line: string, socket: Pick<Socket, "write">, run?: (cmd: Cmd) => Promise<{
41
+ ok: boolean;
42
+ data?: undefined;
43
+ error?: undefined;
44
+ } | {
45
+ ok: boolean;
46
+ data: number;
47
+ error?: undefined;
48
+ } | {
49
+ ok: boolean;
50
+ data: string;
51
+ error?: undefined;
52
+ } | {
53
+ ok: boolean;
54
+ error: string;
55
+ data?: undefined;
56
+ }>, onClose?: () => void): Promise<void>;
57
+ export declare function startDaemon(): void;