From 91834a90e98ce5032081cf7ea9b0683f970e8890 Mon Sep 17 00:00:00 2001 From: xjdeng Date: Tue, 9 Jun 2026 14:53:00 +0800 Subject: [PATCH] fix(plugins): respect PILOT_HOME paths --- ui/server/utils/plugin-loader.js | 24 +++++++------ .../utils/plugin-loader.pilot-home.test.js | 35 +++++++++++++++++++ 2 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 ui/server/utils/plugin-loader.pilot-home.test.js diff --git a/ui/server/utils/plugin-loader.js b/ui/server/utils/plugin-loader.js index 21965c05..db3ef74a 100644 --- a/ui/server/utils/plugin-loader.js +++ b/ui/server/utils/plugin-loader.js @@ -1,10 +1,11 @@ import fs from 'fs'; import path from 'path'; -import os from 'os'; import { spawn } from 'child_process'; +import { resolvePilotHome } from './pilotPaths.js'; -const PLUGINS_DIR = path.join(os.homedir(), '.pilotdeck', 'plugins'); -const PLUGINS_CONFIG_PATH = path.join(os.homedir(), '.pilotdeck', 'plugins.json'); +function getPluginsConfigPath() { + return path.join(resolvePilotHome(), 'plugins.json'); +} const REQUIRED_MANIFEST_FIELDS = ['name', 'displayName', 'entry']; @@ -24,16 +25,18 @@ const ALLOWED_TYPES = ['react', 'module']; const ALLOWED_SLOTS = ['tab']; export function getPluginsDir() { - if (!fs.existsSync(PLUGINS_DIR)) { - fs.mkdirSync(PLUGINS_DIR, { recursive: true }); + const pluginsDir = path.join(resolvePilotHome(), 'plugins'); + if (!fs.existsSync(pluginsDir)) { + fs.mkdirSync(pluginsDir, { recursive: true }); } - return PLUGINS_DIR; + return pluginsDir; } export function getPluginsConfig() { + const configPath = getPluginsConfigPath(); try { - if (fs.existsSync(PLUGINS_CONFIG_PATH)) { - return JSON.parse(fs.readFileSync(PLUGINS_CONFIG_PATH, 'utf-8')); + if (fs.existsSync(configPath)) { + return JSON.parse(fs.readFileSync(configPath, 'utf-8')); } } catch { // Corrupted config, start fresh @@ -42,11 +45,12 @@ export function getPluginsConfig() { } export function savePluginsConfig(config) { - const dir = path.dirname(PLUGINS_CONFIG_PATH); + const configPath = getPluginsConfigPath(); + const dir = path.dirname(configPath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); } - fs.writeFileSync(PLUGINS_CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 0o600 }); + fs.writeFileSync(configPath, JSON.stringify(config, null, 2), { mode: 0o600 }); } export function validateManifest(manifest) { diff --git a/ui/server/utils/plugin-loader.pilot-home.test.js b/ui/server/utils/plugin-loader.pilot-home.test.js new file mode 100644 index 00000000..783fa34f --- /dev/null +++ b/ui/server/utils/plugin-loader.pilot-home.test.js @@ -0,0 +1,35 @@ +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import { afterEach, describe, expect, it } from 'vitest'; +import { getPluginsConfig, getPluginsDir, savePluginsConfig } from './plugin-loader.js'; + +let tempHome; +const originalPilotHome = process.env.PILOT_HOME; + +afterEach(() => { + if (originalPilotHome === undefined) { + delete process.env.PILOT_HOME; + } else { + process.env.PILOT_HOME = originalPilotHome; + } + if (tempHome) { + fs.rmSync(tempHome, { recursive: true, force: true }); + tempHome = undefined; + } +}); + +describe('plugin-loader PilotDeck home resolution', () => { + it('stores plugin paths under PILOT_HOME', () => { + tempHome = fs.mkdtempSync(path.join(os.tmpdir(), 'pilotdeck-plugin-home-')); + process.env.PILOT_HOME = tempHome; + + expect(getPluginsDir()).toBe(path.join(tempHome, 'plugins')); + + const config = { enabled: ['example-plugin'] }; + savePluginsConfig(config); + + expect(fs.existsSync(path.join(tempHome, 'plugins.json'))).toBe(true); + expect(getPluginsConfig()).toEqual(config); + }); +});