{"version":3,"file":"ipc.js","names":[],"sources":["esm/daemon/ipc.js"],"sourcesContent":["import * as net from \"node:net\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { createHash } from \"node:crypto\";\nimport {\n  registerServer,\n  unregisterServer,\n  getAllServers,\n  getAllRoutes,\n  setRoute,\n  clearRoute,\n  findServerById,\n  touchServer,\n  getLastActiveServer\n} from \"./registry\";\nconst SOCKET_DIR = path.join(os.homedir(), \".one\");\nconst SERVERS_FILE = path.join(SOCKET_DIR, \"servers.json\");\nfunction resolveSocketPath() {\n  if (process.platform === \"win32\") {\n    const scope = createHash(\"sha256\").update(SOCKET_DIR).digest(\"hex\").slice(0, 8);\n    return path.win32.join(String.raw`\\\\.\\pipe`, `one-daemon-${scope}`);\n  }\n  return path.join(SOCKET_DIR, \"daemon.sock\");\n}\nconst SOCKET_PATH = resolveSocketPath();\nfunction getSocketPath() {\n  return SOCKET_PATH;\n}\nfunction getServersFilePath() {\n  return SERVERS_FILE;\n}\nfunction ensureSocketDir() {\n  if (!fs.existsSync(SOCKET_DIR)) {\n    fs.mkdirSync(SOCKET_DIR, { recursive: true });\n  }\n}\nfunction writeServerFile(server) {\n  ensureSocketDir();\n  const servers = readServerFiles();\n  const filtered = servers.filter((s) => s.root !== server.root);\n  filtered.push(server);\n  fs.writeFileSync(SERVERS_FILE, JSON.stringify(filtered, null, 2));\n}\nfunction removeServerFile(root) {\n  const servers = readServerFiles();\n  const filtered = servers.filter((s) => s.root !== root);\n  fs.writeFileSync(SERVERS_FILE, JSON.stringify(filtered, null, 2));\n}\nfunction readServerFiles() {\n  try {\n    if (fs.existsSync(SERVERS_FILE)) {\n      return JSON.parse(fs.readFileSync(SERVERS_FILE, \"utf-8\"));\n    }\n  } catch {\n  }\n  return [];\n}\nfunction cleanupSocket() {\n  try {\n    if (fs.existsSync(SOCKET_PATH)) {\n      fs.unlinkSync(SOCKET_PATH);\n    }\n  } catch {\n  }\n}\nfunction createIPCServer(state, onServerRegistered, onServerUnregistered) {\n  ensureSocketDir();\n  cleanupSocket();\n  const server = net.createServer((socket) => {\n    let buffer = \"\";\n    socket.on(\"data\", (data) => {\n      buffer += data.toString();\n      const lines = buffer.split(\"\\n\");\n      buffer = lines.pop() || \"\";\n      for (const line of lines) {\n        if (!line.trim()) continue;\n        try {\n          const message = JSON.parse(line);\n          const response = handleMessage(\n            state,\n            message,\n            onServerRegistered,\n            onServerUnregistered\n          );\n          socket.write(JSON.stringify(response) + \"\\n\");\n        } catch (err) {\n          const errResponse = {\n            type: \"error\",\n            message: err instanceof Error ? err.message : \"Unknown error\"\n          };\n          socket.write(JSON.stringify(errResponse) + \"\\n\");\n        }\n      }\n    });\n    socket.on(\"error\", (err) => {\n      console.error(\"[daemon] IPC socket error:\", err.message);\n    });\n  });\n  server.on(\"error\", (err) => {\n    if (err.code === \"EADDRINUSE\") {\n      console.error(`[daemon] Another daemon is already listening at ${SOCKET_PATH}`);\n    } else {\n      console.error(\"[daemon] IPC server error:\", err.message);\n    }\n    process.exit(1);\n  });\n  server.listen(SOCKET_PATH, () => {\n    if (process.platform !== \"win32\") {\n      fs.chmodSync(SOCKET_PATH, 384);\n    }\n  });\n  return server;\n}\nfunction handleMessage(state, message, onServerRegistered, onServerUnregistered) {\n  switch (message.type) {\n    case \"register\": {\n      const registration = registerServer(state, {\n        port: message.port,\n        bundleId: message.bundleId,\n        root: message.root\n      });\n      onServerRegistered?.(registration.id);\n      return { type: \"registered\", id: registration.id };\n    }\n    case \"unregister\": {\n      unregisterServer(state, message.id);\n      onServerUnregistered?.(message.id);\n      return { type: \"unregistered\" };\n    }\n    case \"route\": {\n      const server = findServerById(state, message.serverId);\n      if (!server) {\n        return { type: \"error\", message: `Server not found: ${message.serverId}` };\n      }\n      setRoute(state, message.bundleId, message.serverId);\n      return { type: \"routed\" };\n    }\n    case \"route-clear\": {\n      clearRoute(state, message.bundleId);\n      return { type: \"routed\" };\n    }\n    case \"status\": {\n      return {\n        type: \"status\",\n        servers: getAllServers(state),\n        routes: getAllRoutes(state)\n      };\n    }\n    case \"ping\": {\n      return { type: \"pong\" };\n    }\n    case \"touch\": {\n      const touched = touchServer(state, message.id);\n      if (!touched) {\n        return { type: \"error\", message: `Server not found: ${message.id}` };\n      }\n      return { type: \"touched\" };\n    }\n    case \"get-last-active\": {\n      const server = getLastActiveServer(state);\n      return { type: \"last-active\", server };\n    }\n    default: {\n      return { type: \"error\", message: `Unknown message type` };\n    }\n  }\n}\nasync function isDaemonRunning() {\n  return new Promise((resolve) => {\n    if (process.platform !== \"win32\" && !fs.existsSync(SOCKET_PATH)) {\n      resolve(false);\n      return;\n    }\n    const client = net.connect(SOCKET_PATH);\n    const timeout = setTimeout(() => {\n      client.destroy();\n      resolve(false);\n    }, 1e3);\n    client.on(\"connect\", () => {\n      clearTimeout(timeout);\n      client.write(JSON.stringify({ type: \"ping\" }) + \"\\n\");\n    });\n    client.on(\"data\", (data) => {\n      clearTimeout(timeout);\n      try {\n        const response = JSON.parse(data.toString().trim());\n        resolve(response.type === \"pong\");\n      } catch {\n        resolve(false);\n      }\n      client.destroy();\n    });\n    client.on(\"error\", () => {\n      clearTimeout(timeout);\n      resolve(false);\n    });\n  });\n}\nasync function sendIPCMessage(message) {\n  return new Promise((resolve, reject) => {\n    const client = net.connect(SOCKET_PATH);\n    let buffer = \"\";\n    const timeout = setTimeout(() => {\n      client.destroy();\n      reject(new Error(\"IPC timeout\"));\n    }, 5e3);\n    client.on(\"connect\", () => {\n      client.write(JSON.stringify(message) + \"\\n\");\n    });\n    client.on(\"data\", (data) => {\n      buffer += data.toString();\n      const lines = buffer.split(\"\\n\");\n      buffer = lines.pop() || \"\";\n      for (const line of lines) {\n        if (!line.trim()) continue;\n        try {\n          clearTimeout(timeout);\n          const response = JSON.parse(line);\n          client.destroy();\n          resolve(response);\n          return;\n        } catch {\n        }\n      }\n    });\n    client.on(\"error\", (err) => {\n      clearTimeout(timeout);\n      reject(err);\n    });\n  });\n}\nasync function registerWithDaemon(opts) {\n  const response = await sendIPCMessage({\n    type: \"register\",\n    ...opts\n  });\n  if (response.type === \"registered\") {\n    return response.id;\n  }\n  if (response.type === \"error\") {\n    throw new Error(response.message);\n  }\n  throw new Error(\"Unexpected response from daemon\");\n}\nasync function unregisterFromDaemon(id) {\n  await sendIPCMessage({ type: \"unregister\", id });\n}\nasync function getDaemonStatus() {\n  const response = await sendIPCMessage({ type: \"status\" });\n  if (response.type === \"status\") {\n    return {\n      servers: response.servers,\n      routes: response.routes\n    };\n  }\n  throw new Error(\"Failed to get daemon status\");\n}\nasync function setDaemonRoute(bundleId, serverId) {\n  const response = await sendIPCMessage({\n    type: \"route\",\n    bundleId,\n    serverId\n  });\n  if (response.type === \"error\") {\n    throw new Error(response.message);\n  }\n}\nasync function clearDaemonRoute(bundleId) {\n  await sendIPCMessage({ type: \"route-clear\", bundleId });\n}\nasync function touchDaemonServer(id) {\n  const response = await sendIPCMessage({ type: \"touch\", id });\n  if (response.type === \"error\") {\n    throw new Error(response.message);\n  }\n}\nasync function getLastActiveDaemonServer() {\n  const response = await sendIPCMessage({ type: \"get-last-active\" });\n  if (response.type === \"last-active\") {\n    return response.server;\n  }\n  throw new Error(\"Failed to get last active server\");\n}\nexport {\n  cleanupSocket,\n  clearDaemonRoute,\n  createIPCServer,\n  ensureSocketDir,\n  getDaemonStatus,\n  getLastActiveDaemonServer,\n  getServersFilePath,\n  getSocketPath,\n  isDaemonRunning,\n  readServerFiles,\n  registerWithDaemon,\n  removeServerFile,\n  sendIPCMessage,\n  setDaemonRoute,\n  touchDaemonServer,\n  unregisterFromDaemon,\n  writeServerFile\n};\n//# sourceMappingURL=ipc.js.map\n"],"mappings":"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"}