import { resolveNotebookPath } from "./chunk-ER4KPD22.js"; import { asyncHandler, createApiModule, defineApiModule, defineEndpoints, successResponse } from "./chunk-74TMTGBG.js"; // shared/modules/remote/api.ts var REMOTE_ENDPOINTS = defineEndpoints({ getConfig: { path: "/config", method: "GET" }, saveConfig: { path: "/config", method: "POST" }, getScreenshot: { path: "/screenshot", method: "GET" }, saveScreenshot: { path: "/screenshot", method: "POST" }, getData: { path: "/data", method: "GET" }, saveData: { path: "/data", method: "POST" } }); // shared/modules/remote/index.ts var REMOTE_MODULE = defineApiModule({ id: "remote", name: "\u8FDC\u7A0B", basePath: "/remote", order: 25, version: "1.0.0", endpoints: REMOTE_ENDPOINTS }); // api/modules/remote/service.ts import fs from "fs/promises"; import path from "path"; var REMOTE_DIR = "remote"; var RemoteService = class { constructor(deps = {}) { this.deps = deps; } getRemoteDir() { const { fullPath } = resolveNotebookPath(REMOTE_DIR); return { relPath: REMOTE_DIR, fullPath }; } getDeviceDir(deviceName) { const safeName = this.sanitizeFileName(deviceName); const { fullPath } = resolveNotebookPath(path.join(REMOTE_DIR, safeName)); return { relPath: path.join(REMOTE_DIR, safeName), fullPath }; } sanitizeFileName(name) { return name.replace(/[<>:"/\\|?*]/g, "_").trim() || "unnamed"; } getDeviceConfigPath(deviceName) { const { fullPath } = this.getDeviceDir(deviceName); return path.join(fullPath, "config.json"); } getDeviceScreenshotPath(deviceName) { const { fullPath } = this.getDeviceDir(deviceName); return path.join(fullPath, "screenshot.png"); } getDeviceDataPath(deviceName) { const { fullPath } = this.getDeviceDir(deviceName); return path.join(fullPath, "data.json"); } async ensureDir(dirPath) { await fs.mkdir(dirPath, { recursive: true }); } async getDeviceNames() { const { fullPath } = this.getRemoteDir(); try { const entries = await fs.readdir(fullPath, { withFileTypes: true }); const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name); return dirs; } catch { return []; } } async getConfig() { const deviceNames = await this.getDeviceNames(); const devices = await Promise.all( deviceNames.map(async (name) => { try { const configPath = this.getDeviceConfigPath(name); const content = await fs.readFile(configPath, "utf-8"); const deviceConfig = JSON.parse(content); return { id: deviceConfig.id || name, deviceName: name, serverHost: deviceConfig.serverHost || "", desktopPort: deviceConfig.desktopPort || 3e3, gitPort: deviceConfig.gitPort || 3001, openCodePort: deviceConfig.openCodePort || 3002, fileTransferPort: deviceConfig.fileTransferPort || 3003, password: deviceConfig.password || "" }; } catch { return { id: name, deviceName: name, serverHost: "", desktopPort: 3e3, gitPort: 3001, openCodePort: 3002, fileTransferPort: 3003, password: "" }; } }) ); return { devices }; } async saveConfig(config) { const { fullPath: remoteDirFullPath } = this.getRemoteDir(); await this.ensureDir(remoteDirFullPath); const existingDevices = await this.getDeviceNames(); const newDeviceNames = config.devices.map((d) => this.sanitizeFileName(d.deviceName)); for (const oldDevice of existingDevices) { if (!newDeviceNames.includes(oldDevice)) { try { const oldDir = path.join(remoteDirFullPath, oldDevice); await fs.rm(oldDir, { recursive: true, force: true }); } catch { } } } for (const device of config.devices) { const deviceDir = this.getDeviceDir(device.deviceName); await this.ensureDir(deviceDir.fullPath); const deviceConfigPath = this.getDeviceConfigPath(device.deviceName); const deviceConfig = { id: device.id, serverHost: device.serverHost, desktopPort: device.desktopPort, gitPort: device.gitPort, openCodePort: device.openCodePort, fileTransferPort: device.fileTransferPort, password: device.password || "" }; await fs.writeFile(deviceConfigPath, JSON.stringify(deviceConfig, null, 2), "utf-8"); } } async getScreenshot(deviceName) { if (!deviceName) { return null; } const screenshotPath = this.getDeviceScreenshotPath(deviceName); try { return await fs.readFile(screenshotPath); } catch { return null; } } async saveScreenshot(dataUrl, deviceName) { console.log("[RemoteService] saveScreenshot:", { deviceName, dataUrlLength: dataUrl?.length }); if (!deviceName || deviceName.trim() === "") { console.warn("[RemoteService] saveScreenshot skipped: no deviceName"); return; } const deviceDir = this.getDeviceDir(deviceName); await this.ensureDir(deviceDir.fullPath); const base64Data = dataUrl.replace(/^data:image\/png;base64,/, ""); const buffer = Buffer.from(base64Data, "base64"); const screenshotPath = this.getDeviceScreenshotPath(deviceName); await fs.writeFile(screenshotPath, buffer); } async getData(deviceName) { if (!deviceName || deviceName.trim() === "") { return null; } const dataPath = this.getDeviceDataPath(deviceName); try { const content = await fs.readFile(dataPath, "utf-8"); return JSON.parse(content); } catch { return null; } } async saveData(data, deviceName) { if (!deviceName || deviceName.trim() === "") { console.warn("[RemoteService] saveData skipped: no deviceName"); return; } const deviceDir = this.getDeviceDir(deviceName); await this.ensureDir(deviceDir.fullPath); const dataPath = this.getDeviceDataPath(deviceName); await fs.writeFile(dataPath, JSON.stringify(data, null, 2), "utf-8"); } }; var createRemoteService = (deps) => { return new RemoteService(deps); }; // api/modules/remote/routes.ts import express from "express"; var createRemoteRoutes = (deps) => { const router = express.Router(); const { remoteService: remoteService2 } = deps; router.get( "/config", asyncHandler(async (req, res) => { const config = await remoteService2.getConfig(); successResponse(res, config); }) ); router.post( "/config", asyncHandler(async (req, res) => { const config = req.body; await remoteService2.saveConfig(config); successResponse(res, null); }) ); router.get( "/screenshot", asyncHandler(async (req, res) => { const deviceName = req.query.device; const buffer = await remoteService2.getScreenshot(deviceName); if (!buffer) { return successResponse(res, ""); } const base64 = `data:image/png;base64,${buffer.toString("base64")}`; successResponse(res, base64); }) ); router.post( "/screenshot", asyncHandler(async (req, res) => { const { dataUrl, deviceName } = req.body; console.log("[Remote] saveScreenshot called:", { deviceName, hasDataUrl: !!dataUrl }); await remoteService2.saveScreenshot(dataUrl, deviceName); successResponse(res, null); }) ); router.get( "/data", asyncHandler(async (req, res) => { const deviceName = req.query.device; const data = await remoteService2.getData(deviceName); successResponse(res, data); }) ); router.post( "/data", asyncHandler(async (req, res) => { const { deviceName, lastConnected } = req.body; const data = {}; if (lastConnected !== void 0) { data.lastConnected = lastConnected; } await remoteService2.saveData(data, deviceName); successResponse(res, null); }) ); return router; }; var remoteService = new RemoteService(); var routes_default = createRemoteRoutes({ remoteService }); // api/modules/remote/index.ts var createRemoteModule = () => { return createApiModule(REMOTE_MODULE, { routes: (container) => { const remoteService2 = container.getSync("remoteService"); return createRemoteRoutes({ remoteService: remoteService2 }); }, lifecycle: { onLoad: (container) => { container.register("remoteService", () => new RemoteService()); } } }); }; var remote_default = createRemoteModule; export { RemoteService, createRemoteService, createRemoteRoutes, createRemoteModule, remote_default };