From 67849c00d52250f9200edde182ba334bc19c5bd4 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Wed, 18 Jun 2025 01:19:10 +0400 Subject: [PATCH] refactor: use tmp for temp dirs and add more robust error handling for updateProxyConfig --- .vscode/settings.json | 1 + nodecar/package.json | 4 ++++ nodecar/src/proxy-storage.ts | 26 +++++++++++++++----------- pnpm-lock.yaml | 18 ++++++++++++++++++ 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 7f3a052..7835781 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,6 +45,7 @@ "Mullvad", "mullvadbrowser", "nodecar", + "nodemon", "ntlm", "objc", "orhun", diff --git a/nodecar/package.json b/nodecar/package.json index ae681a1..aed7df7 100644 --- a/nodecar/package.json +++ b/nodecar/package.json @@ -28,8 +28,12 @@ "get-port": "^7.1.0", "nodemon": "^3.1.10", "proxy-chain": "^2.5.9", + "tmp": "^0.2.3", "ts-node": "^10.9.2", "typescript": "^5.8.3", "typescript-eslint": "^8.34.0" + }, + "devDependencies": { + "@types/tmp": "^0.2.6" } } diff --git a/nodecar/src/proxy-storage.ts b/nodecar/src/proxy-storage.ts index 8de95eb..b34d19f 100644 --- a/nodecar/src/proxy-storage.ts +++ b/nodecar/src/proxy-storage.ts @@ -1,8 +1,7 @@ import fs from "node:fs"; import path from "node:path"; -import os from "node:os"; +import tmp from "tmp"; -// Define the proxy configuration type export interface ProxyConfig { id: string; upstreamUrl: string; @@ -12,10 +11,11 @@ export interface ProxyConfig { pid?: number; } -// Path to store proxy configurations -const STORAGE_DIR = path.join(os.tmpdir(), "donutbrowser", "proxies"); +const STORAGE_DIR = tmp.dirSync({ + prefix: "donutbrowser-proxies-", + unsafeCleanup: true, +}).name; -// Ensure storage directory exists if (!fs.existsSync(STORAGE_DIR)) { fs.mkdirSync(STORAGE_DIR, { recursive: true }); } @@ -88,7 +88,7 @@ export function listProxyConfigs(): ProxyConfig[] { try { const content = fs.readFileSync( path.join(STORAGE_DIR, file), - "utf-8" + "utf-8", ); return JSON.parse(content) as ProxyConfig; } catch (error) { @@ -111,14 +111,18 @@ export function listProxyConfigs(): ProxyConfig[] { export function updateProxyConfig(config: ProxyConfig): boolean { const filePath = path.join(STORAGE_DIR, `${config.id}.json`); - if (!fs.existsSync(filePath)) { - return false; - } - try { + fs.readFileSync(filePath, "utf-8"); fs.writeFileSync(filePath, JSON.stringify(config, null, 2)); return true; } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + console.error( + `Config ${config.id} was deleted while the app was running`, + ); + return false; + } + console.error(`Error updating proxy config ${config.id}:`, error); return false; } @@ -135,7 +139,7 @@ export function isProcessRunning(pid: number): boolean { // but checks if it exists process.kill(pid, 0); return true; - } catch (error) { + } catch { return false; } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 834a66e..d687dc1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -183,6 +183,9 @@ importers: proxy-chain: specifier: ^2.5.9 version: 2.5.9 + tmp: + specifier: ^0.2.3 + version: 0.2.3 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) @@ -192,6 +195,10 @@ importers: typescript-eslint: specifier: ^8.34.0 version: 8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3) + devDependencies: + '@types/tmp': + specifier: ^0.2.6 + version: 0.2.6 packages: @@ -1542,6 +1549,9 @@ packages: '@types/react@19.1.8': resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} + '@types/tmp@0.2.6': + resolution: {integrity: sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==} + '@typescript-eslint/eslint-plugin@8.34.0': resolution: {integrity: sha512-QXwAlHlbcAwNlEEMKQS2RCgJsgXrTJdjXT08xEgbPFa2yYQgVjBymxP5DrfrE7X7iodSzd9qBUHUycdyVJTW1w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3409,6 +3419,10 @@ packages: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} + tmp@0.2.3: + resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} + engines: {node: '>=14.14'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4825,6 +4839,8 @@ snapshots: dependencies: csstype: 3.1.3 + '@types/tmp@0.2.6': {} + '@typescript-eslint/eslint-plugin@8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -7001,6 +7017,8 @@ snapshots: fdir: 6.4.5(picomatch@4.0.2) picomatch: 4.0.2 + tmp@0.2.3: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0