{"_id":"@canlooks/roost-electron","name":"@canlooks/roost-electron","dist-tags":{"latest":"0.0.1"},"versions":{"0.0.1":{"name":"@canlooks/roost-electron","version":"0.0.1","author":{"name":"C.CanLiang","email":"canlooks@gmail.com"},"description":"A backend micro service framework","keywords":["micro service"],"main":"dist/cjs/index.js","module":"dist/esm/index.js","types":"dist/esm/index.d.ts","exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"repository":{"type":"git","url":"git+https://github.com/canlooks/roost.git"},"homepage":"https://github.com/canlooks/roost","bugs":{"url":"https://github.com/canlooks/roost/issues","email":"canlooks@gmail.com"},"license":"MIT","scripts":{"clean":"npx shx rm -rf dist","build":"tsc -m esnext --outDir dist/esm & tsc -m commonjs --outDir dist/cjs","build:alias":"tsc-alias --outDir dist/esm","rebuild":"npm run clean && npm run build && npm run build:alias"},"dependencies":{"@canlooks/roost":"^0.0.1","tslib":"^2.8.1"},"devDependencies":{"@types/express":"^5.0.6","@types/node":"^25.9.1","electron":"^42.3.0","tsc-alias":"^1.8.17","typescript":"^6.0.3"},"_id":"@canlooks/roost-electron@0.0.1","gitHead":"505c5898b5d648b7d7d7fd033290357f58536119","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-913e7duH5ezpfAfFi2i5++XfcOothWtSG/hee5frYzdBYD2eLV1rTiH/cMJw67NNs1Kuz9Bzz9IxGS9WkamQjQ==","shasum":"faa3107c9e22df82643ecbc5e44ddc0866188bad","tarball":"https://registry.npmjs.org/@canlooks/roost-electron/-/roost-electron-0.0.1.tgz","fileCount":11,"unpackedSize":13615,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDJDGoSUO6Zm+t8a920yOIchWvqB0bXnaH+Mr7E6GI+QAIgRmVWFN603rheufQlhKpCi7pm0NoBv45IJGely/GBR38="}]},"_npmUser":{"name":"canlooks","email":"364021661@qq.com"},"directories":{},"maintainers":[{"name":"canlooks","email":"364021661@qq.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/roost-electron_0.0.1_1781149312222_0.41718369033554525"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-11T03:41:52.083Z","0.0.1":"2026-06-11T03:41:52.362Z","modified":"2026-06-11T03:41:52.561Z"},"maintainers":[{"name":"canlooks","email":"364021661@qq.com"}],"description":"A backend micro service framework","homepage":"https://github.com/canlooks/roost","keywords":["micro service"],"repository":{"type":"git","url":"git+https://github.com/canlooks/roost.git"},"author":{"name":"C.CanLiang","email":"canlooks@gmail.com"},"bugs":{"url":"https://github.com/canlooks/roost/issues","email":"canlooks@gmail.com"},"license":"MIT","readme":"# @canlooks/roost-electron\n\nElectron main process plugin for the [Roost](https://github.com/canlooks/roost) microservice framework. Bridges Electron's IPC (Inter-Process Communication) from renderer processes directly to Roost service controllers running in the main process.\n\n## Overview\n\n`@canlooks/roost-electron` is a lightweight plugin that registers an [`ipcMain.handle()`](https://www.electronjs.org/docs/latest/api/ipc-main#ipcmainhandlechannel-listener) listener on a configurable channel. When a renderer process sends an IPC invoke call, the plugin forwards the invocation key and arguments to `app.invoke()`, routing the request to the matching Roost controller action.\n\nPaired with [`@canlooks/roost-electron-renderer`](https://www.npmjs.com/package/@canlooks/roost-electron-renderer) on the renderer side, this enables seamless RPC-style communication where renderer-side controller method calls are transparently proxied via Electron IPC to the main process.\n\n## Installation\n\n```bash\nnpm install @canlooks/roost-electron\n```\n\n**Peer dependencies:**\n- `@canlooks/roost` (core framework)\n- `electron` (main process runtime)\n\n## Quick Start\n\n### Main Process\n\n```typescript\nimport { app, BrowserWindow } from 'electron'\nimport Roost from '@canlooks/roost'\nimport { ElectronMainPlugin } from '@canlooks/roost-electron'\nimport { MyService } from './services/MyService'\n\nasync function main() {\n    const roost = await Roost.create({\n        named: { MyService },\n        plugins: [\n            ElectronMainPlugin()\n        ]\n    })\n\n    const win = new BrowserWindow({\n        webPreferences: {\n            preload: path.join(__dirname, 'preload.js')\n        }\n    })\n    win.loadFile('index.html')\n}\n\napp.whenReady().then(main)\n```\n\n### Renderer Process (with `@canlooks/roost-electron-renderer`)\n\n```typescript\nimport { contextBridge, ipcRenderer } from 'electron'\nimport { createRoostRenderer } from '@canlooks/roost-electron-renderer'\nimport { MyService } from '../services/MyService'\n\ncontextBridge.exposeInMainWorld('roost', {\n    services: await createRoostRenderer(\n        { MyService },\n        { ipcRenderer }\n    )\n})\n```\n\nThen, in the renderer page:\n\n```typescript\n// MyService methods are transparently proxied to the main process\nconst result = await window.roost.services.MyService.doSomething(args)\n```\n\n## API Reference\n\n### `ElectronMainPlugin(options?)`\n\nFactory function that creates a Roost `Plugin` object for the Electron main process.\n\n```typescript\nfunction ElectronMainPlugin(options?: ElectronMainPluginOptions): Plugin\n```\n\n#### `ElectronMainPluginOptions`\n\n| Property  | Type     | Default                       | Description                                                |\n| --------- | -------- | ----------------------------- | ---------------------------------------------------------- |\n| `channel` | `string` | `\"@canlooks/roost-electron\"` | The IPC channel name used for `ipcMain.handle()`. Customize this to avoid conflicts with other IPC handlers. |\n\n#### Return Value\n\nReturns a `Plugin` object conforming to the Roost `Plugin` interface:\n\n```typescript\n{\n    name: 'electron-main',\n    onStaticInjected: (app: Roost) => void\n}\n```\n\n### `registerIpcMain(app, options?)`\n\nLow-level function called internally by the plugin. Registers the `ipcMain.handle()` listener directly.\n\n```typescript\nfunction registerIpcMain(app: Roost, options?: ElectronMainPluginOptions): void\n```\n\n> This is exported for advanced use cases where you need to control registration timing manually. In most cases, use `ElectronMainPlugin()` instead.\n\n## How It Works\n\n### Architecture\n\n```\n┌─────────────────────────────────────────────────────────┐\n│  Renderer Process                                       │\n│  ┌───────────────────────────────────────────────────┐  │\n│  │  createRoostRenderer({ MyService }, { ipcRenderer })│  │\n│  │  → Rewrites MyService methods to call              │  │\n│  │    ipcRenderer.invoke(channel, key, ...args)       │  │\n│  └───────────────────────┬───────────────────────────┘  │\n└──────────────────────────┼──────────────────────────────┘\n                           │ Electron IPC\n┌──────────────────────────┼──────────────────────────────┐\n│  Main Process            │                              │\n│  ┌───────────────────────▼───────────────────────────┐  │\n│  │  ElectronMainPlugin                                │  │\n│  │  → ipcMain.handle(channel, (e, key, ...args) => {  │  │\n│  │      return app.invoke(key, ...args)               │  │\n│  │    })                                              │  │\n│  └───────────────────────┬───────────────────────────┘  │\n│                          │                              │\n│  ┌───────────────────────▼───────────────────────────┐  │\n│  │  Roost App                                         │  │\n│  │  → app.invoke(key, ...args)                        │  │\n│  │  → Route to matching @Controller/@Action           │  │\n│  │  → Execute, return result                          │  │\n│  └───────────────────────────────────────────────────┘  │\n└─────────────────────────────────────────────────────────┘\n```\n\n### Lifecycle\n\nThe plugin hooks into the `onStaticInjected` lifecycle event of Roost:\n\n1. **`Roost.create()`** is called with the plugin in the `plugins` array.\n2. Roost registers all modules and performs dependency injection.\n3. **`onStaticInjected`** fires — the plugin registers `ipcMain.handle()` on the configured channel.\n4. The main process is now ready to receive IPC calls from renderer processes.\n\n### Invocation Flow\n\nWhen a renderer calls `window.roost.services.MyService.doSomething(arg)`:\n\n1. `@canlooks/roost-electron-renderer` rewrites the method to call `ipcRenderer.invoke('@canlooks/roost-electron', 'path/to/action', arg)`.\n2. The IPC message arrives in the main process.\n3. The `ipcMain.handle()` listener receives `(event, key, arg)`.\n4. It calls `app.invoke(key, arg)` on the Roost instance.\n5. Roost's `Invoker` matches the key against registered controllers and actions (path-based, pattern-based, or regex-based routing).\n6. The matched controller method executes and returns a result.\n7. The result is sent back through the IPC channel to the renderer.\n\n## Custom Channel\n\nIf the default channel name conflicts with other IPC handlers in your application, provide a custom channel:\n\n```typescript\nElectronMainPlugin({ channel: 'my-app:rpc' })\n```\n\nMake sure to use the same channel name in the renderer side:\n\n```typescript\ncreateRoostRenderer(\n    { MyService },\n    { ipcRenderer, channel: 'my-app:rpc' }\n)\n```\n\n## Project Structure\n\n```\npackages/electron/\n├── src/\n│   ├── index.ts              # Plugin factory + type exports\n│   └── registerIpcMain.ts    # IPC handler registration\n├── dist/\n│   ├── cjs/                  # CommonJS build output\n│   └── esm/                  # ES Module build output\n├── test/\n├── package.json\n├── tsconfig.json\n├── LICENSE\n└── README.md\n```\n\n## TypeScript\n\nThe package is written in TypeScript and ships with declaration files. TypeScript 6.0+ and `strict` mode are used during development.\n\n### Exports\n\n```typescript\n// Factory function\nexport function ElectronMainPlugin(options?: ElectronMainPluginOptions): Plugin\n\n// Options type\nexport type ElectronMainPluginOptions = {\n    channel?: string\n}\n\n// Low-level registration function\nexport function registerIpcMain(app: Roost, options?: ElectronMainPluginOptions): void\n```\n\n## Related Packages\n\n| Package | Description |\n| ------- | ----------- |\n| [`@canlooks/roost`](https://www.npmjs.com/package/@canlooks/roost) | Core microservice framework |\n| [`@canlooks/roost-electron-renderer`](https://www.npmjs.com/package/@canlooks/roost-electron-renderer) | Renderer-side companion — creates proxy controllers that communicate via IPC |\n\n## License\n\nMIT © [C.CanLiang](https://github.com/canlooks)\n","readmeFilename":"README.md","_rev":"1-c82b6cd967270a4eb733fdd5cea3f016"}