chrome-proc 1.0.0 → 1.0.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.
@@ -0,0 +1,89 @@
1
+ import { execSync } from "child_process";
2
+ import { homedir } from "os";
3
+ import { IPlatformProvider, IProcessManager } from "./types";
4
+ import { generateBashCompletion, generateZshCompletion } from "./completion-helpers";
5
+
6
+ const CHROME_BIN = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
7
+
8
+ function getChromePids(exact = false): number[] {
9
+ try {
10
+ const flag = exact ? "-x" : "-f";
11
+ const output = execSync(`pgrep ${flag} "Google Chrome"`, { encoding: "utf-8" });
12
+ return output
13
+ .trim()
14
+ .split("\n")
15
+ .filter((line) => line.trim() !== "")
16
+ .map((line) => parseInt(line.trim(), 10))
17
+ .filter((pid) => !isNaN(pid));
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+
23
+ function getProcessArgs(pid: number): string {
24
+ try {
25
+ return execSync(`ps -p "${pid}" -o args=`, { encoding: "utf-8" }).trim();
26
+ } catch {
27
+ return "?";
28
+ }
29
+ }
30
+
31
+ function getProcessName(pid: number): string {
32
+ try {
33
+ return execSync(`ps -p "${pid}" -o comm=`, { encoding: "utf-8" }).trim();
34
+ } catch {
35
+ return "?";
36
+ }
37
+ }
38
+
39
+ function killPid(pid: number, signal: "TERM" | "KILL"): boolean {
40
+ try {
41
+ execSync(`/bin/kill -${signal} "${pid}"`, { stdio: "pipe" });
42
+ return true;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+
48
+ function isChromeRunning(): boolean {
49
+ return getChromePids(true).length > 0;
50
+ }
51
+
52
+ const processManager: IProcessManager = {
53
+ getChromePids,
54
+ getProcessArgs,
55
+ getProcessName,
56
+ killPid,
57
+ isChromeRunning,
58
+ };
59
+
60
+ export const darwinProvider: IPlatformProvider = {
61
+ name: "darwin",
62
+
63
+ getChromeExecutablePath(): string {
64
+ return CHROME_BIN;
65
+ },
66
+
67
+ getDefaultChromeDataDir(): string {
68
+ return `${homedir()}/Library/Application Support/Google/Chrome`;
69
+ },
70
+
71
+ getProcessManager(): IProcessManager {
72
+ return processManager;
73
+ },
74
+
75
+ supportedShells(): string[] {
76
+ return ["bash", "zsh"];
77
+ },
78
+
79
+ generateCompletion(shell: string, profileDirs: string[]): string {
80
+ switch (shell) {
81
+ case "bash":
82
+ return generateBashCompletion(profileDirs);
83
+ case "zsh":
84
+ return generateZshCompletion(profileDirs);
85
+ default:
86
+ throw new Error(`Unsupported shell: ${shell}`);
87
+ }
88
+ },
89
+ };
@@ -0,0 +1,18 @@
1
+ import { IPlatformProvider } from "./types";
2
+ import { darwinProvider } from "./darwin";
3
+ import { linuxProvider } from "./linux";
4
+ import { win32Provider } from "./win32";
5
+
6
+ const providers: Record<string, IPlatformProvider> = {
7
+ darwin: darwinProvider,
8
+ linux: linuxProvider,
9
+ win32: win32Provider,
10
+ };
11
+
12
+ export function getPlatform(): IPlatformProvider {
13
+ const p = providers[process.platform];
14
+ if (!p) {
15
+ throw new Error(`Unsupported platform: ${process.platform}`);
16
+ }
17
+ return p;
18
+ }
@@ -0,0 +1,110 @@
1
+ import { execSync } from "child_process";
2
+ import { homedir } from "os";
3
+ import { existsSync } from "fs";
4
+ import { IPlatformProvider, IProcessManager } from "./types";
5
+ import { generateBashCompletion, generateZshCompletion } from "./completion-helpers";
6
+
7
+ const CHROME_CANDIDATES = [
8
+ "/usr/bin/google-chrome",
9
+ "/usr/bin/google-chrome-stable",
10
+ "/usr/bin/chromium",
11
+ "/usr/bin/chromium-browser",
12
+ ];
13
+
14
+ function getChromePids(exact = false): number[] {
15
+ const names = ["chrome", "google-chrome", "google-chrome-stable", "chromium", "chromium-browser"];
16
+ const pids: number[] = [];
17
+ for (const name of names) {
18
+ try {
19
+ const flag = exact ? "-x" : "-f";
20
+ const output = execSync(`pgrep ${flag} "${name}"`, { encoding: "utf-8" });
21
+ output
22
+ .trim()
23
+ .split("\n")
24
+ .filter((line) => line.trim() !== "")
25
+ .map((line) => parseInt(line.trim(), 10))
26
+ .filter((pid) => !isNaN(pid) && !pids.includes(pid))
27
+ .forEach((pid) => pids.push(pid));
28
+ } catch {
29
+ // pgrep exits with code 1 when no matches found
30
+ }
31
+ }
32
+ return pids;
33
+ }
34
+
35
+ function getProcessArgs(pid: number): string {
36
+ try {
37
+ return execSync(`ps -p "${pid}" -o args=`, { encoding: "utf-8" }).trim();
38
+ } catch {
39
+ return "?";
40
+ }
41
+ }
42
+
43
+ function getProcessName(pid: number): string {
44
+ try {
45
+ return execSync(`ps -p "${pid}" -o comm=`, { encoding: "utf-8" }).trim();
46
+ } catch {
47
+ return "?";
48
+ }
49
+ }
50
+
51
+ function killPid(pid: number, signal: "TERM" | "KILL"): boolean {
52
+ try {
53
+ execSync(`kill -${signal} "${pid}"`, { stdio: "pipe" });
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ function isChromeRunning(): boolean {
61
+ return getChromePids(true).length > 0;
62
+ }
63
+
64
+ const processManager: IProcessManager = {
65
+ getChromePids,
66
+ getProcessArgs,
67
+ getProcessName,
68
+ killPid,
69
+ isChromeRunning,
70
+ };
71
+
72
+ function findChrome(): string {
73
+ for (const candidate of CHROME_CANDIDATES) {
74
+ if (existsSync(candidate)) {
75
+ return candidate;
76
+ }
77
+ }
78
+ return CHROME_CANDIDATES[0];
79
+ }
80
+
81
+ export const linuxProvider: IPlatformProvider = {
82
+ name: "linux",
83
+
84
+ getChromeExecutablePath(): string {
85
+ return findChrome();
86
+ },
87
+
88
+ getDefaultChromeDataDir(): string {
89
+ return `${homedir()}/.config/google-chrome`;
90
+ },
91
+
92
+ getProcessManager(): IProcessManager {
93
+ return processManager;
94
+ },
95
+
96
+ supportedShells(): string[] {
97
+ return ["bash", "zsh"];
98
+ },
99
+
100
+ generateCompletion(shell: string, profileDirs: string[]): string {
101
+ switch (shell) {
102
+ case "bash":
103
+ return generateBashCompletion(profileDirs);
104
+ case "zsh":
105
+ return generateZshCompletion(profileDirs);
106
+ default:
107
+ throw new Error(`Unsupported shell: ${shell}`);
108
+ }
109
+ },
110
+ };
@@ -0,0 +1,16 @@
1
+ export interface IProcessManager {
2
+ getChromePids(exact?: boolean): number[];
3
+ getProcessArgs(pid: number): string;
4
+ getProcessName(pid: number): string;
5
+ killPid(pid: number, signal: "TERM" | "KILL"): boolean;
6
+ isChromeRunning(): boolean;
7
+ }
8
+
9
+ export interface IPlatformProvider {
10
+ readonly name: "darwin" | "linux" | "win32";
11
+ getChromeExecutablePath(): string;
12
+ getDefaultChromeDataDir(): string;
13
+ getProcessManager(): IProcessManager;
14
+ supportedShells(): string[];
15
+ generateCompletion(shell: string, profileDirs: string[]): string;
16
+ }
@@ -0,0 +1,122 @@
1
+ import { execSync } from "child_process";
2
+ import { existsSync } from "fs";
3
+ import { IPlatformProvider, IProcessManager } from "./types";
4
+ import { generatePowerShellCompletion } from "./completion-helpers";
5
+
6
+ function getChromePids(_exact = false): number[] {
7
+ try {
8
+ const output = execSync(
9
+ `tasklist /FI "IMAGENAME eq chrome.exe" /FO CSV /NH`,
10
+ { encoding: "utf-8" }
11
+ ).trim();
12
+ if (!output || output.startsWith("INFO:")) return [];
13
+ return output
14
+ .split("\n")
15
+ .map((line) => {
16
+ const match = line.match(/^"[^"]+","(\d+)"/);
17
+ return match ? parseInt(match[1], 10) : NaN;
18
+ })
19
+ .filter((pid) => !isNaN(pid));
20
+ } catch {
21
+ return [];
22
+ }
23
+ }
24
+
25
+ function getProcessArgs(pid: number): string {
26
+ try {
27
+ const output = execSync(
28
+ `powershell.exe -NoProfile -Command "(Get-CimInstance Win32_Process -Filter \\"ProcessId=${pid}\\").CommandLine"`,
29
+ { encoding: "utf-8" }
30
+ ).trim();
31
+ return output || "?";
32
+ } catch {
33
+ return "?";
34
+ }
35
+ }
36
+
37
+ function getProcessName(pid: number): string {
38
+ try {
39
+ const output = execSync(
40
+ `tasklist /FI "PID eq ${pid}" /FO CSV /NH`,
41
+ { encoding: "utf-8" }
42
+ ).trim();
43
+ if (!output || output.startsWith("INFO:")) return "?";
44
+ const match = output.match(/^"([^"]+)"/);
45
+ return match ? match[1] : "?";
46
+ } catch {
47
+ return "?";
48
+ }
49
+ }
50
+
51
+ function killPid(pid: number, signal: "TERM" | "KILL"): boolean {
52
+ try {
53
+ const forceFlag = signal === "KILL" ? "/F" : "";
54
+ execSync(`taskkill /PID ${pid} /T ${forceFlag}`, { stdio: "pipe" });
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ }
60
+
61
+ function isChromeRunning(): boolean {
62
+ return getChromePids().length > 0;
63
+ }
64
+
65
+ const processManager: IProcessManager = {
66
+ getChromePids,
67
+ getProcessArgs,
68
+ getProcessName,
69
+ killPid,
70
+ isChromeRunning,
71
+ };
72
+
73
+ function findChrome(): string {
74
+ const candidates: string[] = [];
75
+ if (process.env.LOCALAPPDATA) {
76
+ candidates.push(`${process.env.LOCALAPPDATA}\\Google\\Chrome\\Application\\chrome.exe`);
77
+ }
78
+ if (process.env.PROGRAMFILES) {
79
+ candidates.push(`${process.env.PROGRAMFILES}\\Google\\Chrome\\Application\\chrome.exe`);
80
+ }
81
+ if (process.env["PROGRAMFILES(X86)"]) {
82
+ candidates.push(`${process.env["PROGRAMFILES(X86)"]}\\Google\\Chrome\\Application\\chrome.exe`);
83
+ }
84
+ for (const candidate of candidates) {
85
+ if (existsSync(candidate)) {
86
+ return candidate;
87
+ }
88
+ }
89
+ return candidates[0] || "chrome.exe";
90
+ }
91
+
92
+ export const win32Provider: IPlatformProvider = {
93
+ name: "win32",
94
+
95
+ getChromeExecutablePath(): string {
96
+ return findChrome();
97
+ },
98
+
99
+ getDefaultChromeDataDir(): string {
100
+ if (process.env.LOCALAPPDATA) {
101
+ return `${process.env.LOCALAPPDATA}\\Google\\Chrome\\User Data`;
102
+ }
103
+ return `${process.env.USERPROFILE || ""}\\AppData\\Local\\Google\\Chrome\\User Data`;
104
+ },
105
+
106
+ getProcessManager(): IProcessManager {
107
+ return processManager;
108
+ },
109
+
110
+ supportedShells(): string[] {
111
+ return ["powershell"];
112
+ },
113
+
114
+ generateCompletion(shell: string, profileDirs: string[]): string {
115
+ switch (shell) {
116
+ case "powershell":
117
+ return generatePowerShellCompletion(profileDirs);
118
+ default:
119
+ throw new Error(`Unsupported shell: ${shell}`);
120
+ }
121
+ },
122
+ };
@@ -1,5 +1,6 @@
1
1
  import { readFileSync, writeFileSync, existsSync, realpathSync, rmSync } from "fs";
2
2
  import { join, resolve } from "path";
3
+ import { getPlatform } from "../platform";
3
4
 
4
5
  export interface ProfileEntry {
5
6
  name: string;
@@ -13,10 +14,10 @@ export interface LocalState {
13
14
 
14
15
  export function getChromeDataDir(): string {
15
16
  const dir = process.env.CHROME_DATA_DIR;
16
- if (!dir) {
17
- throw new Error("CHROME_DATA_DIR environment variable is not set");
17
+ if (dir) {
18
+ return dir;
18
19
  }
19
- return dir;
20
+ return getPlatform().getDefaultChromeDataDir();
20
21
  }
21
22
 
22
23
  export function getLocalStatePath(): string {
@@ -1,34 +1,15 @@
1
- import { execSync } from "child_process";
1
+ import { getPlatform } from "../platform";
2
2
 
3
3
  export function getChromePids(exact = false): number[] {
4
- try {
5
- const flag = exact ? "-x" : "-f";
6
- const output = execSync(`pgrep ${flag} "Google Chrome"`, { encoding: "utf-8" });
7
- return output
8
- .trim()
9
- .split("\n")
10
- .filter((line) => line.trim() !== "")
11
- .map((line) => parseInt(line.trim(), 10))
12
- .filter((pid) => !isNaN(pid));
13
- } catch {
14
- return [];
15
- }
4
+ return getPlatform().getProcessManager().getChromePids(exact);
16
5
  }
17
6
 
18
7
  export function getProcessArgs(pid: number): string {
19
- try {
20
- return execSync(`ps -p "${pid}" -o args=`, { encoding: "utf-8" }).trim();
21
- } catch {
22
- return "?";
23
- }
8
+ return getPlatform().getProcessManager().getProcessArgs(pid);
24
9
  }
25
10
 
26
11
  export function getProcessName(pid: number): string {
27
- try {
28
- return execSync(`ps -p "${pid}" -o comm=`, { encoding: "utf-8" }).trim();
29
- } catch {
30
- return "?";
31
- }
12
+ return getPlatform().getProcessManager().getProcessName(pid);
32
13
  }
33
14
 
34
15
  export function extractDebugPort(args: string): number | null {
@@ -37,14 +18,9 @@ export function extractDebugPort(args: string): number | null {
37
18
  }
38
19
 
39
20
  export function killPid(pid: number, signal: "TERM" | "KILL"): boolean {
40
- try {
41
- execSync(`/bin/kill -${signal} "${pid}"`, { stdio: "pipe" });
42
- return true;
43
- } catch {
44
- return false;
45
- }
21
+ return getPlatform().getProcessManager().killPid(pid, signal);
46
22
  }
47
23
 
48
24
  export function isChromeRunning(): boolean {
49
- return getChromePids(true).length > 0;
25
+ return getPlatform().getProcessManager().isChromeRunning();
50
26
  }