fix: handle permission denied when creating DATA_DIR (#1005)

Fallback to default user directory (~/.9router) when configured
DATA_DIR is not writable (EACCES/EPERM). Other errors still throw.

Co-authored-by: Thiên Toán <toanalien@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Thiên Toán 2026-05-12 09:35:28 +07:00 committed by decolua
parent 94ded9e14e
commit a48fa4eb21
2 changed files with 38 additions and 7 deletions

View file

@ -1,14 +1,29 @@
import fs from "node:fs";
import path from "path";
import os from "os";
const APP_NAME = "9router";
export function getDataDir() {
if (process.env.DATA_DIR) return process.env.DATA_DIR;
function defaultDir() {
if (process.platform === "win32") {
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), APP_NAME);
}
return path.join(os.homedir(), `.${APP_NAME}`);
}
export function getDataDir() {
const configured = process.env.DATA_DIR;
if (!configured) return defaultDir();
try {
fs.mkdirSync(configured, { recursive: true });
return configured;
} catch (e) {
if (e?.code === "EACCES" || e?.code === "EPERM") {
console.warn(`[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME}`);
return defaultDir();
}
throw e;
}
}
export const DATA_DIR = getDataDir();

View file

@ -1,13 +1,29 @@
const fs = require("fs");
const path = require("path");
const os = require("os");
// Single source of truth for data directory — matches localDb.js logic
function getDataDir() {
if (process.env.DATA_DIR) return process.env.DATA_DIR;
const APP_NAME = "9router";
function defaultDir() {
if (process.platform === "win32") {
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), "9router");
return path.join(process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming"), APP_NAME);
}
return path.join(os.homedir(), `.${APP_NAME}`);
}
function getDataDir() {
const configured = process.env.DATA_DIR;
if (!configured) return defaultDir();
try {
fs.mkdirSync(configured, { recursive: true });
return configured;
} catch (e) {
if (e?.code === "EACCES" || e?.code === "EPERM") {
console.warn(`[DATA_DIR] '${configured}' not writable → fallback ~/.${APP_NAME}`);
return defaultDir();
}
throw e;
}
return path.join(os.homedir(), ".9router");
}
const DATA_DIR = getDataDir();