kkrpc 0.2.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +408 -58
  2. package/dist/browser-mod.cjs +188 -689
  3. package/dist/browser-mod.d.cts +48 -47
  4. package/dist/browser-mod.d.cts.map +1 -0
  5. package/dist/browser-mod.d.ts +48 -47
  6. package/dist/browser-mod.d.ts.map +1 -0
  7. package/dist/browser-mod.js +170 -157
  8. package/dist/browser-mod.js.map +1 -0
  9. package/dist/channel-BYtPphRu.js +743 -0
  10. package/dist/channel-BYtPphRu.js.map +1 -0
  11. package/dist/channel-C92Q3vK-.d.ts +150 -0
  12. package/dist/channel-C92Q3vK-.d.ts.map +1 -0
  13. package/dist/channel-CgIjXyNX.cjs +839 -0
  14. package/dist/channel-QTVxXCE5.d.cts +150 -0
  15. package/dist/channel-QTVxXCE5.d.cts.map +1 -0
  16. package/dist/chrome-extension.cjs +83 -0
  17. package/dist/chrome-extension.d.cts +28 -0
  18. package/dist/chrome-extension.d.cts.map +1 -0
  19. package/dist/chrome-extension.d.ts +28 -0
  20. package/dist/chrome-extension.d.ts.map +1 -0
  21. package/dist/chrome-extension.js +73 -0
  22. package/dist/chrome-extension.js.map +1 -0
  23. package/dist/chunk-CUT6urMc.cjs +30 -0
  24. package/dist/deno-BzNLlX8S.d.ts +21 -0
  25. package/dist/deno-BzNLlX8S.d.ts.map +1 -0
  26. package/dist/deno-DAHG1vvV.js +33 -0
  27. package/dist/deno-DAHG1vvV.js.map +1 -0
  28. package/dist/deno-DyicMPIa.cjs +38 -0
  29. package/dist/deno-mod.cjs +10 -380
  30. package/dist/deno-mod.d.cts +5 -19
  31. package/dist/deno-mod.d.ts +5 -19
  32. package/dist/deno-mod.js +4 -10
  33. package/dist/deno-noilmrf7.d.cts +21 -0
  34. package/dist/deno-noilmrf7.d.cts.map +1 -0
  35. package/dist/http-5KkjLA6X.js +97 -0
  36. package/dist/http-5KkjLA6X.js.map +1 -0
  37. package/dist/http-Bq1OqmJP.cjs +109 -0
  38. package/dist/http-Cvnz7K2R.d.cts +37 -0
  39. package/dist/http-Cvnz7K2R.d.cts.map +1 -0
  40. package/dist/http-xFcyKRFw.d.ts +37 -0
  41. package/dist/http-xFcyKRFw.d.ts.map +1 -0
  42. package/dist/http.cjs +18 -459
  43. package/dist/http.d.cts +10 -8
  44. package/dist/http.d.cts.map +1 -0
  45. package/dist/http.d.ts +10 -8
  46. package/dist/http.d.ts.map +1 -0
  47. package/dist/http.js +15 -21
  48. package/dist/http.js.map +1 -0
  49. package/dist/interface-Bt8kzlyu.d.ts +102 -0
  50. package/dist/interface-Bt8kzlyu.d.ts.map +1 -0
  51. package/dist/interface-DIWzRMw1.d.cts +102 -0
  52. package/dist/interface-DIWzRMw1.d.cts.map +1 -0
  53. package/dist/mod.cjs +210 -846
  54. package/dist/mod.d.cts +56 -63
  55. package/dist/mod.d.cts.map +1 -0
  56. package/dist/mod.d.ts +56 -63
  57. package/dist/mod.d.ts.map +1 -0
  58. package/dist/mod.js +187 -198
  59. package/dist/mod.js.map +1 -0
  60. package/dist/socketio.cjs +123 -0
  61. package/dist/socketio.d.cts +44 -0
  62. package/dist/socketio.d.cts.map +1 -0
  63. package/dist/socketio.d.ts +44 -0
  64. package/dist/socketio.d.ts.map +1 -0
  65. package/dist/socketio.js +121 -0
  66. package/dist/socketio.js.map +1 -0
  67. package/dist/tauri-BAorUr9n.d.ts +47 -0
  68. package/dist/tauri-BAorUr9n.d.ts.map +1 -0
  69. package/dist/tauri-C7MVgjRt.js +160 -0
  70. package/dist/tauri-C7MVgjRt.js.map +1 -0
  71. package/dist/tauri-DwFX963h.d.cts +47 -0
  72. package/dist/tauri-DwFX963h.d.cts.map +1 -0
  73. package/dist/tauri-JjaZEH0s.cjs +177 -0
  74. package/dist/transfer-handlers-BbGAQoCs.d.ts +51 -0
  75. package/dist/transfer-handlers-BbGAQoCs.d.ts.map +1 -0
  76. package/dist/transfer-handlers-ZiPAV3RZ.d.cts +51 -0
  77. package/dist/transfer-handlers-ZiPAV3RZ.d.cts.map +1 -0
  78. package/dist/utils-BQ7rl7lY.d.ts +9 -0
  79. package/dist/utils-BQ7rl7lY.d.ts.map +1 -0
  80. package/dist/utils-DsPDtDlJ.d.cts +9 -0
  81. package/dist/utils-DsPDtDlJ.d.cts.map +1 -0
  82. package/package.json +65 -14
  83. package/dist/channel-C01VCxab.d.cts +0 -162
  84. package/dist/channel-C01VCxab.d.ts +0 -162
  85. package/dist/chrome.cjs +0 -447
  86. package/dist/chrome.d.cts +0 -43
  87. package/dist/chrome.d.ts +0 -43
  88. package/dist/chrome.js +0 -18
  89. package/dist/chunk-GRCUBSPR.js +0 -27
  90. package/dist/chunk-INKNKSKA.js +0 -84
  91. package/dist/chunk-KZFPA2BM.js +0 -109
  92. package/dist/chunk-SZGZ2RBM.js +0 -94
  93. package/dist/chunk-YIQVRWAJ.js +0 -321
  94. package/dist/http-D0k1TiAJ.d.cts +0 -33
  95. package/dist/http-D6N0U5-p.d.ts +0 -33
  96. package/dist/tauri-ohph68oo.d.cts +0 -38
  97. package/dist/tauri-pC0wuvjw.d.ts +0 -38
package/README.md CHANGED
@@ -1,36 +1,107 @@
1
- # kkrpc
1
+ <div align="center">
2
2
 
3
- > This project is created for building extension system for a Tauri app (https://github.com/kunkunsh/kunkun).
3
+
4
+ # 🚀 kkrpc
5
+
6
+ ## TypeScript-First RPC Library
7
+
8
+ [![NPM Version](https://img.shields.io/npm/v/kkrpc?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/kkrpc)
9
+ [![JSR Version](https://img.shields.io/jsr/v/@kunkun/kkrpc?style=for-the-badge&logo=deno)](https://jsr.io/@kunkun/kkrpc)
10
+ [![License](https://img.shields.io/npm/l/kkrpc?style=for-the-badge)](https://github.com/kunkunsh/kkrpc/blob/main/LICENSE)
11
+ [![Downloads](https://img.shields.io/npm/dm/kkrpc?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/kkrpc)
12
+ [![GitHub stars](https://img.shields.io/github/stars/kunkunsh/kkrpc?style=for-the-badge&logo=github)](https://github.com/kunkunsh/kkrpc)
13
+ [![Typedoc Documentation](https://img.shields.io/badge/Docs-Typedoc-blue?style=for-the-badge&logo=typescript)](https://kunkunsh.github.io/kkrpc/)
14
+ [![Excalidraw Diagrams](https://img.shields.io/badge/Diagrams-Excalidraw-orange?style=for-the-badge&logo=drawio)](https://excalidraw.com/#json=xp6GbAJVAx3nU-h3PhaxW,oYBNvYmCRsQ2XR3MQo73Ug)
15
+
16
+ </div>
17
+
18
+ > This project was created for building extension system for a Tauri app ([kunkun](https://github.com/kunkunsh/kunkun)).
4
19
  >
5
- > It's potential can be used in other types of apps, so I open sourced it as a standalone package.
20
+ > It can potentially be used in other types of apps, so I open sourced it as a standalone package.
21
+
22
+ **Seamless bi-directional communication between processes, workers, and contexts**
23
+
24
+ Call remote functions as if they were local, with full TypeScript type safety and autocompletion support.
25
+
26
+ **Similar to Comlink but with bidirectional communication** and support for multiple environments - both client and server can expose functions for the other to call across Node.js, Deno, Bun, and browser environments.
27
+
28
+ [**Quick Start**](#-quick-start) • [**Documentation**](https://kunkunsh.github.io/kkrpc/) • [**Examples**](#-examples) • [**API Reference**](https://jsr.io/@kunkun/kkrpc/doc)
29
+
30
+ <div align="center">
31
+
32
+ <img src="https://imgur.com/vR3Lmv0.png" style="max-height: 200px; margin: 10px;"/>
33
+ <img src="https://i.imgur.com/zmOHNfu.png" style="max-height: 250px; margin: 10px;"/>
34
+ <img src="https://imgur.com/u728aVv.png" style="max-height: 400px; margin: 10px;"/>
35
+ <img src="https://i.imgur.com/Gu7jH1v.png" style="max-height: 300px; margin: 10px;"/>
36
+
37
+ </div>
38
+
39
+ ---
40
+
41
+ ## 🌟 Why kkrpc?
42
+
43
+ kkrpc stands out in the crowded RPC landscape by offering **true cross-runtime compatibility** without sacrificing type safety or developer experience. Unlike tRPC (HTTP-only) or Comlink (browser-only), kkrpc enables seamless communication across Node.js, Deno, Bun, and browser environments.
6
44
 
7
- [![NPM Version](https://img.shields.io/npm/v/kkrpc)](https://www.npmjs.com/package/kkrpc)
8
- [![JSR Version](https://jsr.io/badges/@kunkun/kkrpc)](https://jsr.io/@kunkun/kkrpc)
9
- ![GitHub last commit](https://img.shields.io/github/last-commit/kunkunsh/kkrpc)
45
+ ## ✨ Features
10
46
 
11
- > A TypeScript-first RPC library that enables seamless bi-directional communication between processes.
12
- > Call remote functions as if they were local, with full TypeScript type safety and autocompletion support.
47
+ <div align="center">
13
48
 
14
- - [JSR Package](https://jsr.io/@kunkun/kkrpc)
15
- - [NPM Package](https://www.npmjs.com/package/kkrpc)
16
- - [Documentation by JSR](https://jsr.io/@kunkun/kkrpc/doc)
17
- - [Typedoc Documentation](https://kunkunsh.github.io/kkrpc/)
49
+ | Feature | Description |
50
+ |---------|-------------|
51
+ | **🔄 Cross-runtime** | Works seamlessly across Node.js, Deno, Bun, browsers, and more |
52
+ | **🛡️ Type-safe** | Full TypeScript inference and IDE autocompletion support |
53
+ | **↔️ Bidirectional** | Both endpoints can expose and call APIs simultaneously |
54
+ | **🏠 Property Access** | Remote getters/setters with dot notation (`await api.prop`) |
55
+ | **💥 Error Preservation** | Complete error objects across RPC boundaries |
56
+ | **🌐 Multiple Transports** | stdio, HTTP, WebSocket, postMessage, Chrome extensions |
57
+ | **📞 Callback Support** | Remote functions can accept callback functions |
58
+ | **🔗 Nested Calls** | Deep method chaining like `api.math.operations.calculate()` |
59
+ | **📦 Auto Serialization** | Intelligent JSON/superjson detection |
60
+ | **⚡ Zero Config** | No schema files or code generation required |
61
+ | **🚀 Transferable Objects** | Zero-copy transfers for large data (40-100x faster) |
18
62
 
19
- [Excalidraw Diagrams](https://excalidraw.com/#json=xp6GbAJVAx3nU-h3PhaxW,oYBNvYmCRsQ2XR3MQo73Ug)
63
+ </div>
20
64
 
21
- <img src="https://imgur.com/vR3Lmv0.png" style="max-height: 200px;"/>
22
- <img src="https://i.imgur.com/zmOHNfu.png" style="max-height: 250px;"/>
23
- <img src="https://imgur.com/u728aVv.png" style="max-height: 400px;"/>
24
- <img src="https://i.imgur.com/Gu7jH1v.png" style="max-height: 300px;"/>
65
+ ## 🌍 Supported Environments
25
66
 
26
- ## Supported Environments
67
+ <div align="center">
27
68
 
28
- - stdio: RPC over stdio between any combinations of Node.js, Deno, Bun processes
29
- - web: RPC over `postMessage` API and message channel between browser main thread and web workers, or main thread and iframe
30
- - Web Worker API (web standard) is also supported in Deno and Bun, the main thread can call functions in worker and vice versa.
31
- - http: RPC over HTTP like tRPC
32
- - supports any HTTP server (e.g. hono, bun, nodejs http, express, fastify, deno, etc.)
33
- - WebSocket: RPC over WebSocket
69
+ ```mermaid
70
+ graph LR
71
+ A[kkrpc] --> B[Node.js]
72
+ A --> C[Deno]
73
+ A --> D[Bun]
74
+ A --> E[Browser]
75
+ A --> F[Chrome Extension]
76
+ A --> G[Tauri]
77
+
78
+ B -.-> H[stdio]
79
+ C -.-> H
80
+ D -.-> H
81
+
82
+ E -.-> I[postMessage]
83
+ E -.-> J[Web Workers]
84
+ E -.-> K[iframes]
85
+
86
+ F -.-> L[Chrome Ports]
87
+
88
+ G -.-> M[Shell Plugin]
89
+
90
+ style A fill:#ff6b6b,stroke:#333,stroke-width:2px
91
+ ```
92
+
93
+ </div>
94
+
95
+ ### 📡 Transport Protocols
96
+
97
+ | Transport | Use Case | Supported Runtimes |
98
+ |-----------|----------|-------------------|
99
+ | **stdio** | Process-to-process communication | Node.js ↔ Deno ↔ Bun |
100
+ | **postMessage** | Browser context communication | Browser ↔ Web Workers ↔ iframes |
101
+ | **HTTP** | Web API communication | All runtimes |
102
+ | **WebSocket** | Real-time communication | All runtimes |
103
+ | **Socket.IO** | Enhanced real-time with rooms/namespaces | All runtimes |
104
+ | **Chrome Extension** | Extension component communication | Chrome Extension contexts |
34
105
 
35
106
  The core of **kkrpc** design is in `RPCChannel` and `IoInterface`.
36
107
 
@@ -86,9 +157,64 @@ const rpc = new RPCChannel(io, {
86
157
 
87
158
  For backward compatibility, the receiving side will automatically detect the serialization format so older clients can communicate with newer servers and vice versa.
88
159
 
89
- ## Examples
160
+ ## 🚀 Quick Start
161
+
162
+ ### Installation
163
+
164
+ <div align="center">
165
+
166
+ ```bash
167
+ # npm
168
+ npm install kkrpc
169
+
170
+ # yarn
171
+ yarn add kkrpc
172
+
173
+ # pnpm
174
+ pnpm add kkrpc
175
+
176
+ # deno
177
+ import { RPCChannel } from "jsr:@kunkun/kkrpc"
178
+ ```
179
+
180
+ </div>
181
+
182
+ ### Basic Example
183
+
184
+ <div align="center">
185
+
186
+ ```typescript
187
+ // server.ts
188
+ import { RPCChannel, NodeIo } from "kkrpc"
90
189
 
91
- Below are simple examples.
190
+ const api = {
191
+ greet: (name: string) => `Hello, ${name}!`,
192
+ add: (a: number, b: number) => a + b
193
+ }
194
+
195
+ const rpc = new RPCChannel(new NodeIo(process.stdin, process.stdout), {
196
+ expose: api
197
+ })
198
+ ```
199
+
200
+ ```typescript
201
+ // client.ts
202
+ import { RPCChannel, NodeIo } from "kkrpc"
203
+ import { spawn } from "child_process"
204
+
205
+ const worker = spawn("deno", ["run", "server.ts"])
206
+ const rpc = new RPCChannel(new NodeIo(worker.stdout, worker.stdin))
207
+ const api = rpc.getAPI<typeof api>()
208
+
209
+ console.log(await api.greet("World")) // "Hello, World!"
210
+ console.log(await api.add(5, 3)) // 8
211
+ ```
212
+
213
+ </div>
214
+
215
+ ## 📚 Examples
216
+
217
+ Below are simple examples to get you started quickly.
92
218
 
93
219
  ### Stdio Example
94
220
 
@@ -111,6 +237,81 @@ const api = parent.getAPI()
111
237
  expect(await api.add(1, 2)).toBe(3)
112
238
  ```
113
239
 
240
+ ### Property Access Example
241
+
242
+ kkrpc supports direct property access and mutation across RPC boundaries:
243
+
244
+ ```ts
245
+ // Define API with properties
246
+ interface API {
247
+ add(a: number, b: number): Promise<number>
248
+ counter: number
249
+ settings: {
250
+ theme: string
251
+ notifications: {
252
+ enabled: boolean
253
+ }
254
+ }
255
+ }
256
+
257
+ const api = rpc.getAPI<API>()
258
+
259
+ // Property getters (using await for remote access)
260
+ const currentCount = await api.counter
261
+ const theme = await api.settings.theme
262
+ const notificationsEnabled = await api.settings.notifications.enabled
263
+
264
+ // Property setters (direct assignment)
265
+ api.counter = 42
266
+ api.settings.theme = "dark"
267
+ api.settings.notifications.enabled = true
268
+
269
+ // Verify changes
270
+ console.log(await api.counter) // 42
271
+ console.log(await api.settings.theme) // "dark"
272
+ ```
273
+
274
+ ### Enhanced Error Preservation
275
+
276
+ kkrpc preserves complete error information across RPC boundaries:
277
+
278
+ ```ts
279
+ // Custom error class
280
+ class DatabaseError extends Error {
281
+ constructor(message: string, public code: number, public query: string) {
282
+ super(message)
283
+ this.name = 'DatabaseError'
284
+ }
285
+ }
286
+
287
+ // API with error-throwing method
288
+ const apiImplementation = {
289
+ async getUserById(id: string) {
290
+ if (!id) {
291
+ const error = new DatabaseError("Invalid user ID", 400, "SELECT * FROM users WHERE id = ?")
292
+ error.timestamp = new Date().toISOString()
293
+ error.requestId = generateRequestId()
294
+ throw error
295
+ }
296
+ // ... normal logic
297
+ }
298
+ }
299
+
300
+ // Error handling on client side
301
+ try {
302
+ await api.getUserById("")
303
+ } catch (error) {
304
+ // All error properties are preserved:
305
+ console.log(error.name) // "DatabaseError"
306
+ console.log(error.message) // "Invalid user ID"
307
+ console.log(error.code) // 400
308
+ console.log(error.query) // "SELECT * FROM users WHERE id = ?"
309
+ console.log(error.stack) // Full stack trace
310
+ console.log(error.timestamp) // ISO timestamp
311
+ console.log(error.requestId) // Request ID
312
+ }
313
+ ```
314
+
114
315
  ### Web Worker Example
115
316
 
116
317
  ```ts
@@ -135,6 +336,51 @@ const sum = await api.add(1, 2)
135
336
  expect(sum).toBe(3)
136
337
  ```
137
338
 
339
+ ### Transferable Objects Example
340
+
341
+ kkrpc supports zero-copy transfer of large data structures using browser's native transferable objects. This provides 40-100x performance improvement for large binary data transfers.
342
+
343
+ ```ts
344
+ import { RPCChannel, WorkerParentIO, transfer } from "kkrpc/browser"
345
+
346
+ const worker = new Worker("worker.js")
347
+ const io = new WorkerParentIO(worker)
348
+ const rpc = new RPCChannel(io)
349
+ const api = rpc.getAPI<{
350
+ processBuffer(buffer: ArrayBuffer): Promise<number>
351
+ generateData(size: number): Promise<ArrayBuffer>
352
+ }>()
353
+
354
+ // Create a large buffer (10MB)
355
+ const buffer = new ArrayBuffer(10 * 1024 * 1024)
356
+ console.log("Before transfer:", buffer.byteLength) // 10485760
357
+
358
+ // Transfer buffer to worker (zero-copy)
359
+ const result = await api.processBuffer(transfer(buffer, [buffer]))
360
+ console.log("Worker processed:", result, "bytes")
361
+
362
+ // Buffer is now neutered (transferred ownership)
363
+ console.log("After transfer:", buffer.byteLength) // 0
364
+
365
+ // Get data back from worker (also transferred)
366
+ const newBuffer = await api.generateData(5 * 1024 * 1024)
367
+ console.log("Received from worker:", newBuffer.byteLength) // 5242880
368
+ ```
369
+
370
+ **Key Benefits:**
371
+ - **Zero-copy performance**: No serialization/deserialization overhead
372
+ - **Memory efficient**: Ownership transfers without copying
373
+ - **Automatic fallback**: Graceful degradation for non-transferable transports
374
+ - **Type-safe**: Full TypeScript support
375
+
376
+ **Supported Transferable Types:**
377
+ - `ArrayBuffer` - Binary data buffers
378
+ - `MessagePort` - Communication channels
379
+ - `ImageBitmap` - Decoded image data
380
+ - `OffscreenCanvas` - Off-screen canvas rendering
381
+ - `ReadableStream`/`WritableStream` - Streaming data
382
+ - And more... [See MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Transferable_objects)
383
+
138
384
  ### HTTP Example
139
385
 
140
386
  Codesandbox: https://codesandbox.io/p/live/4a349334-0b04-4352-89f9-cf1955553ae7
@@ -208,52 +454,60 @@ console.log("Sum: ", sum)
208
454
 
209
455
  ### Chrome Extension Example
210
456
 
457
+ For Chrome extensions, use the dedicated `ChromePortIO` adapter for reliable, port-based communication.
458
+
211
459
  #### `background.ts`
212
460
 
213
461
  ```ts
214
- import { ChromeBackgroundIO, RPCChannel } from "kkrpc"
215
- import type { API } from "./api"
462
+ import { ChromePortIO, RPCChannel } from "kkrpc/chrome-extension";
463
+ import type { BackgroundAPI, ContentAPI } from "./types";
216
464
 
217
- // Store RPC channels for each tab
218
- const rpcChannels = new Map<number, RPCChannel<API, {}>>()
465
+ const backgroundAPI: BackgroundAPI = {
466
+ async getExtensionVersion() {
467
+ return chrome.runtime.getManifest().version;
468
+ },
469
+ };
219
470
 
220
- // Listen for tab connections
221
471
  chrome.runtime.onConnect.addListener((port) => {
222
- if (port.sender?.tab?.id) {
223
- const tabId = port.sender.tab.id
224
- const io = new ChromeBackgroundIO(tabId)
225
- const rpc = new RPCChannel(io, { expose: backgroundAPI })
226
- rpcChannels.set(tabId, rpc)
227
-
228
- port.onDisconnect.addListener(() => {
229
- rpcChannels.delete(tabId)
230
- })
231
- }
232
- })
472
+ if (port.name === "content-to-background") {
473
+ const io = new ChromePortIO(port);
474
+ const rpc = new RPCChannel(io, { expose: backgroundAPI });
475
+ // Handle disconnect
476
+ port.onDisconnect.addListener(() => io.destroy());
477
+ }
478
+ });
233
479
  ```
234
480
 
235
481
  #### `content.ts`
236
482
 
237
483
  ```ts
238
- import { ChromeContentIO, RPCChannel } from "kkrpc"
239
- import type { API } from "./api"
240
-
241
- const io = new ChromeContentIO()
242
- const rpc = new RPCChannel<API, API>(io, {
243
- expose: {
244
- updateUI: async (data) => {
245
- document.body.innerHTML = data.message
246
- return true
247
- }
248
- }
249
- })
484
+ import { ChromePortIO, RPCChannel } from "kkrpc/chrome-extension";
485
+ import type { BackgroundAPI, ContentAPI } from "./types";
250
486
 
251
- // Get API from background script
252
- const api = rpc.getAPI()
253
- const data = await api.getData()
254
- console.log(data) // { message: "Hello from background!" }
487
+ const contentAPI: ContentAPI = {
488
+ async getPageTitle() {
489
+ return document.title;
490
+ },
491
+ };
492
+
493
+ const port = chrome.runtime.connect({ name: "content-to-background" });
494
+ const io = new ChromePortIO(port);
495
+ const rpc = new RPCChannel<ContentAPI, BackgroundAPI>(io, { expose: contentAPI });
496
+
497
+ const backgroundAPI = rpc.getAPI();
498
+
499
+ // Example call
500
+ backgroundAPI.getExtensionVersion().then(version => {
501
+ console.log("Extension version:", version);
502
+ });
255
503
  ```
256
504
 
505
+ **Chrome Extension Features:**
506
+ - **Port-based**: Uses `chrome.runtime.Port` for stable, long-lived connections.
507
+ - **Bidirectional**: Both sides can expose and call APIs.
508
+ - **Type-safe**: Full TypeScript support for your APIs.
509
+ - **Reliable**: Handles connection lifecycle and cleanup.
510
+
257
511
  ### Tauri Example
258
512
 
259
513
  Call functions in bun/node/deno processes from Tauri app with JS/TS.
@@ -323,3 +577,99 @@ async function spawnCmd(runtime: "deno" | "bun" | "node") {
323
577
  I provided a sample tauri app in `examples/tauri-demo`.
324
578
 
325
579
  ![Sample Tauri App](https://i.imgur.com/nkDwRHk.png)
580
+
581
+ ## 🆚 Comparison with Alternatives
582
+
583
+ <div align="center">
584
+
585
+ | Feature | kkrpc | tRPC | Comlink |
586
+ |---------|-------|------|---------|
587
+ | **Cross-runtime** | ✅ Node.js, Deno, Bun, Browser | ❌ Node.js/Browser only | ❌ Browser only |
588
+ | **Bidirectional** | ✅ Both sides can call APIs | ❌ Client calls server only | ✅ Both sides can call APIs |
589
+ | **Type Safety** | ✅ Full TypeScript support | ✅ Full TypeScript support | ✅ TypeScript support |
590
+ | **Transport Layers** | ✅ stdio, HTTP, WebSocket, postMessage, Chrome Extension | ❌ HTTP only | ❌ postMessage only |
591
+ | **Error Preservation** | ✅ Complete error objects | ⚠️ Limited error serialization | ⚠️ Limited error serialization |
592
+ | **Property Access** | ✅ Remote getters/setters | ❌ Methods only | ❌ Methods only |
593
+ | **Zero Config** | ✅ No code generation | ✅ No code generation | ✅ No code generation |
594
+ | **Callbacks** | ✅ Function parameters | ❌ No callbacks | ✅ Function parameters |
595
+ | **Transferable Objects** | ✅ Zero-copy transfers (40-100x faster) | ❌ Not supported | ✅ Basic support |
596
+
597
+ </div>
598
+
599
+ ### When to choose kkrpc
600
+
601
+ - **Cross-process communication**: Need to communicate between different runtimes (Node.js ↔ Deno, Browser ↔ Node.js, etc.)
602
+ - **Extension systems**: Building plugin architectures or extension systems
603
+ - **Tauri applications**: Communicating between Tauri frontend and backend processes
604
+ - **Chrome extensions**: Complex communication between content scripts, background pages, and popups
605
+ - **Multi-worker architectures**: Coordinating multiple web workers with different responsibilities
606
+ - **Desktop applications**: Electron/Tauri apps with multiple processes
607
+
608
+ ### When to choose tRPC
609
+
610
+ - **REST API replacement**: Building type-safe APIs for web applications
611
+ - **HTTP-only communication**: When you only need HTTP-based communication
612
+ - **React/Next.js integration**: When you need tight integration with React ecosystem
613
+ - **Database-driven APIs**: When building traditional client-server applications
614
+
615
+ ### When to choose Comlink
616
+
617
+ - **Browser-only applications**: Simple web worker communication in browsers
618
+ - **Lightweight needs**: When you only need basic postMessage abstraction
619
+ - **No cross-runtime requirements**: When all your code runs in browsers
620
+ - **Simple worker patterns**: When you don't need advanced features like property access
621
+
622
+ ## 🔍 Keywords & SEO
623
+
624
+ **Primary Keywords**: RPC, TypeScript, Remote Procedure Call, Type-safe, Bidirectional, Cross-runtime
625
+
626
+ **Secondary Keywords**: Node.js, Deno, Bun, Browser, Web Worker, Chrome Extension, Tauri, IPC, Inter-process Communication
627
+
628
+ **Use Cases**: Extension system, Plugin architecture, Microservices, Worker communication, Cross-context communication
629
+
630
+ ## 📦 Package Information
631
+
632
+ <div align="center">
633
+
634
+ | Platform | Package | Link |
635
+ |----------|---------|------|
636
+ | **NPM** | `kkrpc` | [![NPM](https://img.shields.io/badge/npm-kkrpc-red?style=flat-square&logo=npm)](https://www.npmjs.com/package/kkrpc) |
637
+ | **JSR** | `@kunkun/kkrpc` | [![JSR](https://img.shields.io/badge/jsr-@kunkun/kkrpc-blue?style=flat-square&logo=deno)](https://jsr.io/@kunkun/kkrpc) |
638
+ | **GitHub** | Repository | [![GitHub](https://img.shields.io/badge/github-kkrpc-black?style=flat-square&logo=github)](https://github.com/kunkunsh/kkrpc) |
639
+ | **Docs** | Typedoc | [![Docs](https://img.shields.io/badge/docs-typedoc-blue?style=flat-square&logo=typescript)](https://kunkunsh.github.io/kkrpc/) |
640
+ | **Examples** | Code Samples | [![Examples](https://img.shields.io/badge/examples-code-green?style=flat-square&logo=github)](https://github.com/kunkunsh/kkrpc/tree/main/examples) |
641
+
642
+ </div>
643
+
644
+ ## 🤝 Contributing
645
+
646
+ <div align="center">
647
+
648
+ **Contributions are welcome!** 🎉
649
+
650
+ Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
651
+
652
+ [![GitHub issues](https://img.shields.io/github/issues/kunkunsh/kkrpc?style=flat-square&logo=github)](https://github.com/kunkunsh/kkrpc/issues)
653
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/kunkunsh/kkrpc?style=flat-square&logo=github)](https://github.com/kunkunsh/kkrpc/pulls)
654
+
655
+ </div>
656
+
657
+ ## 📄 License
658
+
659
+ <div align="center">
660
+
661
+ [![License](https://img.shields.io/npm/l/kkrpc?style=flat-square)](https://github.com/kunkunsh/kkrpc/blob/main/LICENSE)
662
+
663
+ MIT © [kunkunsh](https://github.com/kunkunsh)
664
+
665
+ </div>
666
+
667
+ ---
668
+
669
+ <div align="center">
670
+
671
+ **⭐ Star this repo if it helped you!**
672
+
673
+ Made with ❤️ by the kkrpc team
674
+
675
+ </div>