Initial open-source release

This commit is contained in:
Will Chen
2025-04-11 09:37:05 -07:00
commit 43f67e0739
208 changed files with 45476 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
import { ChildProcess } from "node:child_process";
import treeKill from "tree-kill";
// Define a type for the value stored in runningApps
export interface RunningAppInfo {
process: ChildProcess;
processId: number;
}
// Store running app processes
export const runningApps = new Map<number, RunningAppInfo>();
// Global counter for process IDs
let processCounterValue = 0;
// Getter and setter for processCounter to allow modification from outside
export const processCounter = {
get value(): number {
return processCounterValue;
},
set value(newValue: number) {
processCounterValue = newValue;
},
increment(): number {
return ++processCounterValue;
},
};
/**
* Kills a running process with its child processes
* @param process The child process to kill
* @param pid The process ID
* @returns A promise that resolves when the process is closed or timeout
*/
export function killProcess(process: ChildProcess): Promise<void> {
return new Promise<void>((resolve) => {
// Add timeout to prevent hanging
const timeout = setTimeout(() => {
console.warn(
`Timeout waiting for process (PID: ${process.pid}) to close. Force killing may be needed.`
);
resolve();
}, 5000); // 5-second timeout
process.on("close", (code, signal) => {
clearTimeout(timeout);
console.log(
`Received 'close' event for process (PID: ${process.pid}) with code ${code}, signal ${signal}.`
);
resolve();
});
// Handle potential errors during kill/close sequence
process.on("error", (err) => {
clearTimeout(timeout);
console.error(
`Error during stop sequence for process (PID: ${process.pid}): ${err.message}`
);
resolve();
});
// Ensure PID exists before attempting to kill
if (process.pid) {
// Use tree-kill to terminate the entire process tree
console.log(
`Attempting to tree-kill process tree starting at PID ${process.pid}.`
);
treeKill(process.pid, "SIGTERM", (err: Error | undefined) => {
if (err) {
console.warn(
`tree-kill error for PID ${process.pid}: ${err.message}`
);
} else {
console.log(
`tree-kill signal sent successfully to PID ${process.pid}.`
);
}
});
} else {
console.warn(`Cannot tree-kill process: PID is undefined.`);
}
});
}
/**
* Removes an app from the running apps map if it's the current process
* @param appId The app ID
* @param process The process to check against
*/
export function removeAppIfCurrentProcess(
appId: number,
process: ChildProcess
): void {
const currentAppInfo = runningApps.get(appId);
if (currentAppInfo && currentAppInfo.process === process) {
runningApps.delete(appId);
console.log(
`Removed app ${appId} (processId ${currentAppInfo.processId}) from running map. Current size: ${runningApps.size}`
);
} else {
console.log(
`App ${appId} process was already removed or replaced in running map. Ignoring.`
);
}
}