kkrpc 0.1.2 → 0.2.0-beta.2

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 CHANGED
@@ -12,6 +12,8 @@
12
12
  - [Documentation by JSR](https://jsr.io/@kunkun/kkrpc/doc)
13
13
  - [Typedoc Documentation](https://kunkunsh.github.io/kkrpc/)
14
14
 
15
+ [Excalidraw Diagrams](https://excalidraw.com/#json=otqFU25B2sSjweA4Sbq9l,7-eY_bzFrGAXLNkOVpQ2Tg)
16
+
15
17
  ![](https://imgur.com/vR3Lmv0.png)
16
18
  ![](https://imgur.com/u728aVv.png)
17
19
  ![](https://imgur.com/2ycWgVQ.png)
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // browser-mod.ts
@@ -337,29 +347,14 @@ var IframeChildIO = class {
337
347
  var import_node_buffer = require("buffer");
338
348
 
339
349
  // src/serialization.ts
340
- function replacer(key, value) {
341
- if (value instanceof Uint8Array) {
342
- return {
343
- type: "Uint8Array",
344
- data: Array.from(value)
345
- // Convert to regular array
346
- };
347
- }
348
- return value;
349
- }
350
- function reviver(key, value) {
351
- if (value && value.type === "Uint8Array" && Array.isArray(value.data)) {
352
- return new Uint8Array(value.data);
353
- }
354
- return value;
355
- }
350
+ var import_superjson = __toESM(require("superjson"), 1);
356
351
  function serializeMessage(message) {
357
- return JSON.stringify(message, replacer) + "\n";
352
+ return import_superjson.default.stringify(message) + "\n";
358
353
  }
359
354
  function deserializeMessage(message) {
360
355
  return new Promise((resolve, reject) => {
361
356
  try {
362
- const parsed = JSON.parse(message, reviver);
357
+ const parsed = import_superjson.default.parse(message);
363
358
  resolve(parsed);
364
359
  } catch (error) {
365
360
  console.error("failed to parse message", typeof message, message, error);
@@ -368,12 +363,12 @@ function deserializeMessage(message) {
368
363
  });
369
364
  }
370
365
  function serializeResponse(response) {
371
- return JSON.stringify(response) + "\n";
366
+ return import_superjson.default.stringify(response) + "\n";
372
367
  }
373
368
  function deserializeResponse(response) {
374
369
  return new Promise((resolve, reject) => {
375
370
  try {
376
- const parsed = JSON.parse(response);
371
+ const parsed = import_superjson.default.parse(response);
377
372
  resolve(parsed);
378
373
  } catch (error) {
379
374
  console.error("failed to parse response", response);
@@ -400,12 +395,25 @@ var RPCChannel = class {
400
395
  count = 0;
401
396
  messageStr = "";
402
397
  apiImplementation;
398
+ /**
399
+ * Exposes a local API implementation that can be called remotely
400
+ * @param api The local API implementation to expose
401
+ */
403
402
  expose(api) {
404
403
  this.apiImplementation = api;
405
404
  }
405
+ /**
406
+ * Returns the IO interface used by this channel
407
+ * @returns The IO interface instance
408
+ */
406
409
  getIO() {
407
410
  return this.io;
408
411
  }
412
+ /**
413
+ * Listens for incoming messages on the IO interface
414
+ * Handles message buffering and parsing
415
+ * @private
416
+ */
409
417
  async listen() {
410
418
  while (true) {
411
419
  const buffer = await this.io.read();
@@ -430,6 +438,11 @@ var RPCChannel = class {
430
438
  }
431
439
  }
432
440
  }
441
+ /**
442
+ * Handles a single message string by parsing and routing it
443
+ * @param messageStr The message string to handle
444
+ * @private
445
+ */
433
446
  async handleMessageStr(messageStr) {
434
447
  this.count++;
435
448
  return deserializeMessage(messageStr).then((parsedMessage) => {
@@ -446,7 +459,12 @@ var RPCChannel = class {
446
459
  console.log(`(kkrpc stdout passthrough):`, messageStr);
447
460
  });
448
461
  }
449
- // Send a method call to the other process
462
+ /**
463
+ * Calls a method on the remote API
464
+ * @param method The name of the method to call
465
+ * @param args Arguments to pass to the remote method
466
+ * @returns Promise that resolves with the result of the remote call
467
+ */
450
468
  callMethod(method, args) {
451
469
  return new Promise((resolve, reject) => {
452
470
  const messageId = generateUUID();
@@ -476,7 +494,11 @@ var RPCChannel = class {
476
494
  this.io.write(serializeMessage(message));
477
495
  });
478
496
  }
479
- // Handle response to a request we sent
497
+ /**
498
+ * Handles responses received from remote method calls
499
+ * @param response The response message to handle
500
+ * @private
501
+ */
480
502
  handleResponse(response) {
481
503
  const { id } = response;
482
504
  const { result, error } = response.args;
@@ -489,7 +511,11 @@ var RPCChannel = class {
489
511
  delete this.pendingRequests[id];
490
512
  }
491
513
  }
492
- // Handle incoming requests from the other process using a Proxy
514
+ /**
515
+ * Handles incoming method call requests from the remote endpoint
516
+ * @param request The request message to handle
517
+ * @private
518
+ */
493
519
  handleRequest(request) {
494
520
  const { id, method, args } = request;
495
521
  const methodPath = method.split(".");
@@ -526,6 +552,12 @@ var RPCChannel = class {
526
552
  this.sendError(id, error.message ?? error.toString());
527
553
  }
528
554
  }
555
+ /**
556
+ * Invokes a callback on the remote endpoint
557
+ * @param callbackId The ID of the callback to invoke
558
+ * @param args Arguments to pass to the callback
559
+ * @private
560
+ */
529
561
  invokeCallback(callbackId, args) {
530
562
  const message = {
531
563
  id: generateUUID(),
@@ -535,6 +567,11 @@ var RPCChannel = class {
535
567
  };
536
568
  this.io.write(serializeMessage(message));
537
569
  }
570
+ /**
571
+ * Handles callback invocations received from the remote endpoint
572
+ * @param message The callback message to handle
573
+ * @private
574
+ */
538
575
  handleCallback(message) {
539
576
  const { method: callbackId, args } = message;
540
577
  const callback = this.callbacks[callbackId];
@@ -544,7 +581,12 @@ var RPCChannel = class {
544
581
  console.error(`Callback with id ${callbackId} not found`);
545
582
  }
546
583
  }
547
- // Send a response to a request
584
+ /**
585
+ * Sends a successful response back to the remote endpoint
586
+ * @param id The ID of the request being responded to
587
+ * @param result The result to send back
588
+ * @private
589
+ */
548
590
  sendResponse(id, result) {
549
591
  const response = {
550
592
  id,
@@ -554,7 +596,12 @@ var RPCChannel = class {
554
596
  };
555
597
  this.io.write(serializeMessage(response));
556
598
  }
557
- // Send an error response
599
+ /**
600
+ * Sends an error response back to the remote endpoint
601
+ * @param id The ID of the request being responded to
602
+ * @param error The error message to send back
603
+ * @private
604
+ */
558
605
  sendError(id, error) {
559
606
  const response = {
560
607
  id,
@@ -564,6 +611,12 @@ var RPCChannel = class {
564
611
  };
565
612
  this.io.write(serializeMessage(response));
566
613
  }
614
+ /**
615
+ * Creates a nested proxy object for chaining remote method calls
616
+ * @param chain Array of method names in the chain
617
+ * @returns Proxy object that transforms property access into remote method calls
618
+ * @private
619
+ */
567
620
  createNestedProxy(chain = []) {
568
621
  return new Proxy(() => {
569
622
  }, {
@@ -579,16 +632,17 @@ var RPCChannel = class {
579
632
  }
580
633
  });
581
634
  }
635
+ /**
636
+ * Returns a proxy object that represents the remote API
637
+ * Methods called on this proxy will be executed on the remote endpoint
638
+ * @returns Proxy object representing the remote API
639
+ */
582
640
  getAPI() {
583
641
  return this.createNestedProxy();
584
642
  }
585
643
  /**
586
- * Free up the callback map and cache
587
- * If you use callbacks a lot, you could get memory leak.
588
- * e.g. If you use anonymous callback function in a 5000 iterations loop,
589
- * you will get 5000 callbacks in cache. It's a better idea to free them.
590
- *
591
- * If you use a named callback function, there will be only one entry in the cache.
644
+ * Frees up memory by clearing stored callbacks and callback cache
645
+ * Useful when dealing with many anonymous callback functions to prevent memory leaks
592
646
  */
593
647
  freeCallbacks() {
594
648
  this.callbacks = {};
@@ -1,7 +1,7 @@
1
- export { a as WorkerChildIO, W as WorkerParentIO } from './worker-ByZFWF48.cjs';
1
+ export { a as WorkerChildIO, W as WorkerParentIO } from './worker-72MNjMgj.cjs';
2
2
  export { ChromeBackgroundIO, ChromeContentIO, Message, Response, deserializeMessage, deserializeResponse, generateUUID, serializeMessage, serializeResponse } from './chrome.cjs';
3
- import { D as DestroyableIoInterface } from './channel-CGr_xSbe.cjs';
4
- export { I as IoInterface, R as RPCChannel } from './channel-CGr_xSbe.cjs';
3
+ import { D as DestroyableIoInterface } from './channel-D6ZClufP.cjs';
4
+ export { I as IoInterface, R as RPCChannel } from './channel-D6ZClufP.cjs';
5
5
  import 'node:buffer';
6
6
 
7
7
  /**
@@ -1,7 +1,7 @@
1
- export { a as WorkerChildIO, W as WorkerParentIO } from './worker-sUTyf1YL.js';
1
+ export { a as WorkerChildIO, W as WorkerParentIO } from './worker-DiYJxxHW.js';
2
2
  export { ChromeBackgroundIO, ChromeContentIO, Message, Response, deserializeMessage, deserializeResponse, generateUUID, serializeMessage, serializeResponse } from './chrome.js';
3
- import { D as DestroyableIoInterface } from './channel-CGr_xSbe.js';
4
- export { I as IoInterface, R as RPCChannel } from './channel-CGr_xSbe.js';
3
+ import { D as DestroyableIoInterface } from './channel-D6ZClufP.js';
4
+ export { I as IoInterface, R as RPCChannel } from './channel-D6ZClufP.js';
5
5
  import 'node:buffer';
6
6
 
7
7
  /**
@@ -13,7 +13,7 @@ import {
13
13
  generateUUID,
14
14
  serializeMessage,
15
15
  serializeResponse
16
- } from "./chunk-ASRFS3R2.js";
16
+ } from "./chunk-ZSSFWNSX.js";
17
17
 
18
18
  // src/adapters/iframe.ts
19
19
  var DESTROY_SIGNAL = "__DESTROY__";
@@ -0,0 +1,128 @@
1
+ import { Buffer } from 'node:buffer';
2
+
3
+ /**
4
+ * This file contains the common interface for building a bidirectional communication channel.
5
+ */
6
+
7
+ /**
8
+ * Theoretically, any bidirectional channel with read and write can be used to build a RPC interface.
9
+ */
10
+ interface IoInterface {
11
+ name: string;
12
+ read(): Promise<Buffer | Uint8Array | string | null>;
13
+ write(data: string): Promise<void>;
14
+ }
15
+ /**
16
+ * A destroyable IoInterface, mainly for iframe and web worker communication
17
+ * Used for cleaning up resources, e.g. MessageChannel
18
+ */
19
+ interface DestroyableIoInterface extends IoInterface {
20
+ destroy(): void;
21
+ signalDestroy(): void;
22
+ }
23
+
24
+ /**
25
+ * A bidirectional Stdio IPC channel in RPC style.
26
+ * This allows 2 JS/TS processes to call each other's API like using libraries in RPC style,
27
+ * without needing to deal with `argv`, `stdin`, `stdout` directly.
28
+ */
29
+ declare class RPCChannel<LocalAPI extends Record<string, any>, RemoteAPI extends Record<string, any>, Io extends IoInterface = IoInterface> {
30
+ private io;
31
+ private pendingRequests;
32
+ private callbacks;
33
+ private callbackCache;
34
+ private count;
35
+ private messageStr;
36
+ private apiImplementation?;
37
+ constructor(io: Io, options?: {
38
+ expose?: LocalAPI;
39
+ });
40
+ /**
41
+ * Exposes a local API implementation that can be called remotely
42
+ * @param api The local API implementation to expose
43
+ */
44
+ expose(api: LocalAPI): void;
45
+ /**
46
+ * Returns the IO interface used by this channel
47
+ * @returns The IO interface instance
48
+ */
49
+ getIO(): Io;
50
+ /**
51
+ * Listens for incoming messages on the IO interface
52
+ * Handles message buffering and parsing
53
+ * @private
54
+ */
55
+ private listen;
56
+ /**
57
+ * Handles a single message string by parsing and routing it
58
+ * @param messageStr The message string to handle
59
+ * @private
60
+ */
61
+ private handleMessageStr;
62
+ /**
63
+ * Calls a method on the remote API
64
+ * @param method The name of the method to call
65
+ * @param args Arguments to pass to the remote method
66
+ * @returns Promise that resolves with the result of the remote call
67
+ */
68
+ callMethod<T extends keyof RemoteAPI>(method: T, args: any[]): Promise<void>;
69
+ /**
70
+ * Handles responses received from remote method calls
71
+ * @param response The response message to handle
72
+ * @private
73
+ */
74
+ private handleResponse;
75
+ /**
76
+ * Handles incoming method call requests from the remote endpoint
77
+ * @param request The request message to handle
78
+ * @private
79
+ */
80
+ private handleRequest;
81
+ /**
82
+ * Invokes a callback on the remote endpoint
83
+ * @param callbackId The ID of the callback to invoke
84
+ * @param args Arguments to pass to the callback
85
+ * @private
86
+ */
87
+ private invokeCallback;
88
+ /**
89
+ * Handles callback invocations received from the remote endpoint
90
+ * @param message The callback message to handle
91
+ * @private
92
+ */
93
+ private handleCallback;
94
+ /**
95
+ * Sends a successful response back to the remote endpoint
96
+ * @param id The ID of the request being responded to
97
+ * @param result The result to send back
98
+ * @private
99
+ */
100
+ private sendResponse;
101
+ /**
102
+ * Sends an error response back to the remote endpoint
103
+ * @param id The ID of the request being responded to
104
+ * @param error The error message to send back
105
+ * @private
106
+ */
107
+ private sendError;
108
+ /**
109
+ * Creates a nested proxy object for chaining remote method calls
110
+ * @param chain Array of method names in the chain
111
+ * @returns Proxy object that transforms property access into remote method calls
112
+ * @private
113
+ */
114
+ private createNestedProxy;
115
+ /**
116
+ * Returns a proxy object that represents the remote API
117
+ * Methods called on this proxy will be executed on the remote endpoint
118
+ * @returns Proxy object representing the remote API
119
+ */
120
+ getAPI(): RemoteAPI;
121
+ /**
122
+ * Frees up memory by clearing stored callbacks and callback cache
123
+ * Useful when dealing with many anonymous callback functions to prevent memory leaks
124
+ */
125
+ freeCallbacks(): void;
126
+ }
127
+
128
+ export { type DestroyableIoInterface as D, type IoInterface as I, RPCChannel as R };
@@ -0,0 +1,128 @@
1
+ import { Buffer } from 'node:buffer';
2
+
3
+ /**
4
+ * This file contains the common interface for building a bidirectional communication channel.
5
+ */
6
+
7
+ /**
8
+ * Theoretically, any bidirectional channel with read and write can be used to build a RPC interface.
9
+ */
10
+ interface IoInterface {
11
+ name: string;
12
+ read(): Promise<Buffer | Uint8Array | string | null>;
13
+ write(data: string): Promise<void>;
14
+ }
15
+ /**
16
+ * A destroyable IoInterface, mainly for iframe and web worker communication
17
+ * Used for cleaning up resources, e.g. MessageChannel
18
+ */
19
+ interface DestroyableIoInterface extends IoInterface {
20
+ destroy(): void;
21
+ signalDestroy(): void;
22
+ }
23
+
24
+ /**
25
+ * A bidirectional Stdio IPC channel in RPC style.
26
+ * This allows 2 JS/TS processes to call each other's API like using libraries in RPC style,
27
+ * without needing to deal with `argv`, `stdin`, `stdout` directly.
28
+ */
29
+ declare class RPCChannel<LocalAPI extends Record<string, any>, RemoteAPI extends Record<string, any>, Io extends IoInterface = IoInterface> {
30
+ private io;
31
+ private pendingRequests;
32
+ private callbacks;
33
+ private callbackCache;
34
+ private count;
35
+ private messageStr;
36
+ private apiImplementation?;
37
+ constructor(io: Io, options?: {
38
+ expose?: LocalAPI;
39
+ });
40
+ /**
41
+ * Exposes a local API implementation that can be called remotely
42
+ * @param api The local API implementation to expose
43
+ */
44
+ expose(api: LocalAPI): void;
45
+ /**
46
+ * Returns the IO interface used by this channel
47
+ * @returns The IO interface instance
48
+ */
49
+ getIO(): Io;
50
+ /**
51
+ * Listens for incoming messages on the IO interface
52
+ * Handles message buffering and parsing
53
+ * @private
54
+ */
55
+ private listen;
56
+ /**
57
+ * Handles a single message string by parsing and routing it
58
+ * @param messageStr The message string to handle
59
+ * @private
60
+ */
61
+ private handleMessageStr;
62
+ /**
63
+ * Calls a method on the remote API
64
+ * @param method The name of the method to call
65
+ * @param args Arguments to pass to the remote method
66
+ * @returns Promise that resolves with the result of the remote call
67
+ */
68
+ callMethod<T extends keyof RemoteAPI>(method: T, args: any[]): Promise<void>;
69
+ /**
70
+ * Handles responses received from remote method calls
71
+ * @param response The response message to handle
72
+ * @private
73
+ */
74
+ private handleResponse;
75
+ /**
76
+ * Handles incoming method call requests from the remote endpoint
77
+ * @param request The request message to handle
78
+ * @private
79
+ */
80
+ private handleRequest;
81
+ /**
82
+ * Invokes a callback on the remote endpoint
83
+ * @param callbackId The ID of the callback to invoke
84
+ * @param args Arguments to pass to the callback
85
+ * @private
86
+ */
87
+ private invokeCallback;
88
+ /**
89
+ * Handles callback invocations received from the remote endpoint
90
+ * @param message The callback message to handle
91
+ * @private
92
+ */
93
+ private handleCallback;
94
+ /**
95
+ * Sends a successful response back to the remote endpoint
96
+ * @param id The ID of the request being responded to
97
+ * @param result The result to send back
98
+ * @private
99
+ */
100
+ private sendResponse;
101
+ /**
102
+ * Sends an error response back to the remote endpoint
103
+ * @param id The ID of the request being responded to
104
+ * @param error The error message to send back
105
+ * @private
106
+ */
107
+ private sendError;
108
+ /**
109
+ * Creates a nested proxy object for chaining remote method calls
110
+ * @param chain Array of method names in the chain
111
+ * @returns Proxy object that transforms property access into remote method calls
112
+ * @private
113
+ */
114
+ private createNestedProxy;
115
+ /**
116
+ * Returns a proxy object that represents the remote API
117
+ * Methods called on this proxy will be executed on the remote endpoint
118
+ * @returns Proxy object representing the remote API
119
+ */
120
+ getAPI(): RemoteAPI;
121
+ /**
122
+ * Frees up memory by clearing stored callbacks and callback cache
123
+ * Useful when dealing with many anonymous callback functions to prevent memory leaks
124
+ */
125
+ freeCallbacks(): void;
126
+ }
127
+
128
+ export { type DestroyableIoInterface as D, type IoInterface as I, RPCChannel as R };