kkrpc 0.2.2 → 0.4.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.
- package/README.md +129 -33
- package/dist/browser-mod.cjs +254 -104
- package/dist/browser-mod.d.cts +4 -5
- package/dist/browser-mod.d.ts +4 -5
- package/dist/browser-mod.js +5 -7
- package/dist/{channel-C01VCxab.d.cts → channel-B27IYR-w.d.cts} +65 -9
- package/dist/{channel-C01VCxab.d.ts → channel-B27IYR-w.d.ts} +65 -9
- package/dist/{chrome.cjs → chrome-extension.cjs} +289 -69
- package/dist/chrome-extension.d.cts +31 -0
- package/dist/chrome-extension.d.ts +31 -0
- package/dist/chrome-extension.js +85 -0
- package/dist/{chunk-GRCUBSPR.js → chunk-4HW5GG4Z.js} +1 -2
- package/dist/{chunk-YIQVRWAJ.js → chunk-H4MEJ5S3.js} +244 -9
- package/dist/deno-mod.cjs +243 -11
- package/dist/deno-mod.d.cts +3 -4
- package/dist/deno-mod.d.ts +3 -4
- package/dist/deno-mod.js +2 -2
- package/dist/{http-D0k1TiAJ.d.cts → http-Bmw5laGn.d.cts} +1 -1
- package/dist/{http-D6N0U5-p.d.ts → http-Oe0LUTM7.d.ts} +1 -1
- package/dist/http.cjs +242 -9
- package/dist/http.d.cts +2 -3
- package/dist/http.d.ts +2 -3
- package/dist/http.js +1 -1
- package/dist/mod.cjs +255 -109
- package/dist/mod.d.cts +7 -13
- package/dist/mod.d.ts +7 -13
- package/dist/mod.js +10 -11
- package/dist/{tauri-ohph68oo.d.cts → tauri-Dw5KiKI3.d.cts} +1 -1
- package/dist/{tauri-pC0wuvjw.d.ts → tauri-hhlO_PlO.d.ts} +1 -1
- package/dist/utils-B1qZZBwh.d.cts +7 -0
- package/dist/utils-B1qZZBwh.d.ts +7 -0
- package/package.json +12 -12
- package/dist/chrome.d.cts +0 -43
- package/dist/chrome.d.ts +0 -43
- package/dist/chrome.js +0 -18
- package/dist/chunk-INKNKSKA.js +0 -84
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> This project is created for building extension system for a Tauri app (https://github.com/kunkunsh/kunkun).
|
|
4
4
|
>
|
|
5
|
-
> It
|
|
5
|
+
> It can potentially be used in other types of apps, so I open sourced it as a standalone package.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/kkrpc)
|
|
8
8
|
[](https://jsr.io/@kunkun/kkrpc)
|
|
@@ -23,6 +23,19 @@
|
|
|
23
23
|
<img src="https://imgur.com/u728aVv.png" style="max-height: 400px;"/>
|
|
24
24
|
<img src="https://i.imgur.com/Gu7jH1v.png" style="max-height: 300px;"/>
|
|
25
25
|
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- **Cross-runtime compatibility**: Works seamlessly across Node.js, Deno, Bun, browsers, and more
|
|
29
|
+
- **Type-safe remote calls**: Full TypeScript inference and IDE autocompletion support
|
|
30
|
+
- **Bidirectional communication**: Both endpoints can expose and call APIs simultaneously
|
|
31
|
+
- **Property access**: Remote property getters and setters with dot notation (`await api.prop`, `api.prop = value`)
|
|
32
|
+
- **Enhanced error preservation**: Complete error object preservation across RPC boundaries including stack traces, causes, and custom properties
|
|
33
|
+
- **Multiple transport protocols**: stdio, HTTP, WebSocket, postMessage, Chrome extensions
|
|
34
|
+
- **Callback support**: Remote functions can accept callback functions as parameters
|
|
35
|
+
- **Nested object calls**: Deep method chaining like `api.math.operations.calculate()`
|
|
36
|
+
- **Automatic serialization**: Intelligent detection between JSON and superjson formats
|
|
37
|
+
- **Zero configuration**: No schema files or code generation required
|
|
38
|
+
|
|
26
39
|
## Supported Environments
|
|
27
40
|
|
|
28
41
|
- stdio: RPC over stdio between any combinations of Node.js, Deno, Bun processes
|
|
@@ -111,6 +124,81 @@ const api = parent.getAPI()
|
|
|
111
124
|
expect(await api.add(1, 2)).toBe(3)
|
|
112
125
|
```
|
|
113
126
|
|
|
127
|
+
### Property Access Example
|
|
128
|
+
|
|
129
|
+
kkrpc supports direct property access and mutation across RPC boundaries:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// Define API with properties
|
|
133
|
+
interface API {
|
|
134
|
+
add(a: number, b: number): Promise<number>
|
|
135
|
+
counter: number
|
|
136
|
+
settings: {
|
|
137
|
+
theme: string
|
|
138
|
+
notifications: {
|
|
139
|
+
enabled: boolean
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const api = rpc.getAPI<API>()
|
|
145
|
+
|
|
146
|
+
// Property getters (using await for remote access)
|
|
147
|
+
const currentCount = await api.counter
|
|
148
|
+
const theme = await api.settings.theme
|
|
149
|
+
const notificationsEnabled = await api.settings.notifications.enabled
|
|
150
|
+
|
|
151
|
+
// Property setters (direct assignment)
|
|
152
|
+
api.counter = 42
|
|
153
|
+
api.settings.theme = "dark"
|
|
154
|
+
api.settings.notifications.enabled = true
|
|
155
|
+
|
|
156
|
+
// Verify changes
|
|
157
|
+
console.log(await api.counter) // 42
|
|
158
|
+
console.log(await api.settings.theme) // "dark"
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Enhanced Error Preservation
|
|
162
|
+
|
|
163
|
+
kkrpc preserves complete error information across RPC boundaries:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
// Custom error class
|
|
167
|
+
class DatabaseError extends Error {
|
|
168
|
+
constructor(message: string, public code: number, public query: string) {
|
|
169
|
+
super(message)
|
|
170
|
+
this.name = 'DatabaseError'
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// API with error-throwing method
|
|
175
|
+
const apiImplementation = {
|
|
176
|
+
async getUserById(id: string) {
|
|
177
|
+
if (!id) {
|
|
178
|
+
const error = new DatabaseError("Invalid user ID", 400, "SELECT * FROM users WHERE id = ?")
|
|
179
|
+
error.timestamp = new Date().toISOString()
|
|
180
|
+
error.requestId = generateRequestId()
|
|
181
|
+
throw error
|
|
182
|
+
}
|
|
183
|
+
// ... normal logic
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Error handling on client side
|
|
188
|
+
try {
|
|
189
|
+
await api.getUserById("")
|
|
190
|
+
} catch (error) {
|
|
191
|
+
// All error properties are preserved:
|
|
192
|
+
console.log(error.name) // "DatabaseError"
|
|
193
|
+
console.log(error.message) // "Invalid user ID"
|
|
194
|
+
console.log(error.code) // 400
|
|
195
|
+
console.log(error.query) // "SELECT * FROM users WHERE id = ?"
|
|
196
|
+
console.log(error.stack) // Full stack trace
|
|
197
|
+
console.log(error.timestamp) // ISO timestamp
|
|
198
|
+
console.log(error.requestId) // Request ID
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
114
202
|
### Web Worker Example
|
|
115
203
|
|
|
116
204
|
```ts
|
|
@@ -208,52 +296,60 @@ console.log("Sum: ", sum)
|
|
|
208
296
|
|
|
209
297
|
### Chrome Extension Example
|
|
210
298
|
|
|
299
|
+
For Chrome extensions, use the dedicated `ChromePortIO` adapter for reliable, port-based communication.
|
|
300
|
+
|
|
211
301
|
#### `background.ts`
|
|
212
302
|
|
|
213
303
|
```ts
|
|
214
|
-
import {
|
|
215
|
-
import type {
|
|
304
|
+
import { ChromePortIO, RPCChannel } from "kkrpc/chrome-extension";
|
|
305
|
+
import type { BackgroundAPI, ContentAPI } from "./types";
|
|
216
306
|
|
|
217
|
-
|
|
218
|
-
|
|
307
|
+
const backgroundAPI: BackgroundAPI = {
|
|
308
|
+
async getExtensionVersion() {
|
|
309
|
+
return chrome.runtime.getManifest().version;
|
|
310
|
+
},
|
|
311
|
+
};
|
|
219
312
|
|
|
220
|
-
// Listen for tab connections
|
|
221
313
|
chrome.runtime.onConnect.addListener((port) => {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
rpcChannels.delete(tabId)
|
|
230
|
-
})
|
|
231
|
-
}
|
|
232
|
-
})
|
|
314
|
+
if (port.name === "content-to-background") {
|
|
315
|
+
const io = new ChromePortIO(port);
|
|
316
|
+
const rpc = new RPCChannel(io, { expose: backgroundAPI });
|
|
317
|
+
// Handle disconnect
|
|
318
|
+
port.onDisconnect.addListener(() => io.destroy());
|
|
319
|
+
}
|
|
320
|
+
});
|
|
233
321
|
```
|
|
234
322
|
|
|
235
323
|
#### `content.ts`
|
|
236
324
|
|
|
237
325
|
```ts
|
|
238
|
-
import {
|
|
239
|
-
import type {
|
|
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
|
-
})
|
|
326
|
+
import { ChromePortIO, RPCChannel } from "kkrpc/chrome-extension";
|
|
327
|
+
import type { BackgroundAPI, ContentAPI } from "./types";
|
|
250
328
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
329
|
+
const contentAPI: ContentAPI = {
|
|
330
|
+
async getPageTitle() {
|
|
331
|
+
return document.title;
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const port = chrome.runtime.connect({ name: "content-to-background" });
|
|
336
|
+
const io = new ChromePortIO(port);
|
|
337
|
+
const rpc = new RPCChannel<ContentAPI, BackgroundAPI>(io, { expose: contentAPI });
|
|
338
|
+
|
|
339
|
+
const backgroundAPI = rpc.getAPI();
|
|
340
|
+
|
|
341
|
+
// Example call
|
|
342
|
+
backgroundAPI.getExtensionVersion().then(version => {
|
|
343
|
+
console.log("Extension version:", version);
|
|
344
|
+
});
|
|
255
345
|
```
|
|
256
346
|
|
|
347
|
+
**Chrome Extension Features:**
|
|
348
|
+
- **Port-based**: Uses `chrome.runtime.Port` for stable, long-lived connections.
|
|
349
|
+
- **Bidirectional**: Both sides can expose and call APIs.
|
|
350
|
+
- **Type-safe**: Full TypeScript support for your APIs.
|
|
351
|
+
- **Reliable**: Handles connection lifecycle and cleanup.
|
|
352
|
+
|
|
257
353
|
### Tauri Example
|
|
258
354
|
|
|
259
355
|
Call functions in bun/node/deno processes from Tauri app with JS/TS.
|