navflow-browser-server
Version:
Standalone Playwright browser server for NavFlow - enables browser automation with API key authentication, workspace device management, session sync, LLM discovery tools, and requires Node.js v22+
181 lines • 7.19 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataDirectory = void 0;
const path_1 = __importDefault(require("path"));
const promises_1 = __importDefault(require("fs/promises"));
const os_1 = __importDefault(require("os"));
/**
* DataDirectory utility for managing persistent data storage across browser-server versions
* Ensures session data persists through npm version updates by using global OS directories
*/
class DataDirectory {
/**
* Get the global data directory path based on OS
* - macOS/Linux: ~/.navflow/
* - Windows: %APPDATA%/NavFlow/
*/
static getGlobalDataDir() {
if (this.globalDataDir) {
return this.globalDataDir;
}
const homeDir = os_1.default.homedir();
const platform = os_1.default.platform();
if (platform === 'win32') {
// Windows: Use APPDATA
const appData = process.env.APPDATA || path_1.default.join(homeDir, 'AppData', 'Roaming');
this.globalDataDir = path_1.default.join(appData, 'NavFlow');
}
else {
// macOS/Linux: Use home directory
this.globalDataDir = path_1.default.join(homeDir, '.navflow');
}
return this.globalDataDir;
}
/**
* Get the global cookies directory
*/
static getCookiesDir() {
return path_1.default.join(this.getGlobalDataDir(), 'cookies');
}
/**
* Get the global sessions directory
*/
static getSessionsDir() {
return path_1.default.join(this.getGlobalDataDir(), 'sessions');
}
/**
* Get the global device config directory
*/
static getDeviceConfigDir() {
return path_1.default.join(this.getGlobalDataDir(), 'device');
}
/**
* Ensure all necessary directories exist
*/
static async ensureDirectories() {
const dirs = [
this.getGlobalDataDir(),
this.getCookiesDir(),
this.getSessionsDir(),
this.getDeviceConfigDir()
];
for (const dir of dirs) {
try {
await promises_1.default.mkdir(dir, { recursive: true });
}
catch (error) {
console.error(`Failed to create directory ${dir}:`, error);
}
}
}
/**
* Check if legacy data exists in the old location
*/
static async hasLegacyData() {
const legacyCookiesDir = path_1.default.join(process.cwd(), 'data', 'cookies');
const legacySessionsDir = path_1.default.join(process.cwd(), 'data', 'sessions');
const checkDir = async (dirPath) => {
try {
const stats = await promises_1.default.stat(dirPath);
if (stats.isDirectory()) {
const files = await promises_1.default.readdir(dirPath);
return files.length > 0;
}
}
catch {
// Directory doesn't exist
}
return false;
};
return {
cookies: await checkDir(legacyCookiesDir),
sessions: await checkDir(legacySessionsDir)
};
}
/**
* Migrate legacy data from old location to global location
*/
static async migrateLegacyData() {
const legacyCheck = await this.hasLegacyData();
const errors = [];
let migrated = false;
if (!legacyCheck.cookies && !legacyCheck.sessions) {
return { migrated: false, errors: [] };
}
console.log('🔄 Migrating session data to global location...');
// Ensure global directories exist
await this.ensureDirectories();
// Migrate cookies
if (legacyCheck.cookies) {
try {
const legacyCookiesDir = path_1.default.join(process.cwd(), 'data', 'cookies');
const globalCookiesDir = this.getCookiesDir();
const cookieFiles = await promises_1.default.readdir(legacyCookiesDir);
for (const file of cookieFiles) {
if (file.endsWith('.json')) {
const sourcePath = path_1.default.join(legacyCookiesDir, file);
const targetPath = path_1.default.join(globalCookiesDir, file);
// Only copy if target doesn't exist (don't overwrite newer data)
try {
await promises_1.default.access(targetPath);
console.log(` ⏭️ Skipping ${file} (already exists in global location)`);
}
catch {
await promises_1.default.copyFile(sourcePath, targetPath);
console.log(` ✅ Migrated cookie file: ${file}`);
migrated = true;
}
}
}
}
catch (error) {
errors.push(`Failed to migrate cookies: ${error.message}`);
}
}
// Migrate sessions
if (legacyCheck.sessions) {
try {
const legacySessionsDir = path_1.default.join(process.cwd(), 'data', 'sessions');
const globalSessionsDir = this.getSessionsDir();
const sessionFiles = await promises_1.default.readdir(legacySessionsDir);
for (const file of sessionFiles) {
if (file.endsWith('.json')) {
const sourcePath = path_1.default.join(legacySessionsDir, file);
const targetPath = path_1.default.join(globalSessionsDir, file);
// Only copy if target doesn't exist
try {
await promises_1.default.access(targetPath);
console.log(` ⏭️ Skipping ${file} (already exists in global location)`);
}
catch {
await promises_1.default.copyFile(sourcePath, targetPath);
console.log(` ✅ Migrated session file: ${file}`);
migrated = true;
}
}
}
}
catch (error) {
errors.push(`Failed to migrate sessions: ${error.message}`);
}
}
if (migrated) {
console.log(`✅ Session data migrated to: ${this.getGlobalDataDir()}`);
}
return { migrated, errors };
}
/**
* Display data directory information
*/
static displayInfo() {
console.log(`📁 Session data directory: ${this.getGlobalDataDir()}`);
console.log(` • Cookies: ${this.getCookiesDir()}`);
console.log(` • Sessions: ${this.getSessionsDir()}`);
}
}
exports.DataDirectory = DataDirectory;
DataDirectory.globalDataDir = null;
//# sourceMappingURL=DataDirectory.js.map