js-rpc2 2.3.0 → 2.3.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/package.json +1 -1
- package/src/lib.js +66 -25
- package/src/lib.test.js +5 -2
- package/src/server.js +16 -12
- package/src/types.ts +0 -5
package/package.json
CHANGED
package/src/lib.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { Packr } from 'msgpackr'
|
2
2
|
|
3
3
|
/**
|
4
|
-
* @import { CALLBACK_ITEM,
|
4
|
+
* @import { CALLBACK_ITEM, RPC_DATA, RPC_DATA_ARG_ITEM } from "./types.js"
|
5
5
|
*/
|
6
6
|
|
7
7
|
const JS_RPC_WITH_CRYPTO = true
|
@@ -407,8 +407,7 @@ export function buildRpcItemData(items) {
|
|
407
407
|
}
|
408
408
|
|
409
409
|
/**
|
410
|
-
* @
|
411
|
-
* @param {ExtensionApi<T>} extension
|
410
|
+
* @param {object} extension
|
412
411
|
* @param {WritableStreamDefaultWriter<Uint8Array<ArrayBuffer>>} writer
|
413
412
|
* @param {Uint8Array<ArrayBuffer>} buffer
|
414
413
|
* @param {(msg:string)=>void} logger
|
@@ -501,13 +500,11 @@ export function createRPCProxy(apiInvoke) {
|
|
501
500
|
*/
|
502
501
|
|
503
502
|
/**
|
504
|
-
* @template T
|
505
503
|
* @param {{
|
506
504
|
* rpcKey: string;
|
507
|
-
* extension:
|
505
|
+
* extension: object;
|
508
506
|
* logger?: (msg:string)=>void;
|
509
507
|
* async?: boolean;
|
510
|
-
* context?:any;
|
511
508
|
* }} param
|
512
509
|
*/
|
513
510
|
export function createRpcServerHelper(param) {
|
@@ -517,8 +514,6 @@ export function createRpcServerHelper(param) {
|
|
517
514
|
let writer = encode.writable.getWriter()
|
518
515
|
decode.readable.pipeTo(new WritableStream({
|
519
516
|
async write(buffer) {
|
520
|
-
let asyncLocalStorage = param.extension.asyncLocalStorage
|
521
|
-
asyncLocalStorage?.enterWith(param.context)
|
522
517
|
if (param.async) {
|
523
518
|
rpcRunServerDecodeBuffer(param.extension, writer, buffer, param.logger).catch(console.error)
|
524
519
|
} else {
|
@@ -763,11 +758,55 @@ export function createRpcClientHttp(param) {
|
|
763
758
|
}
|
764
759
|
|
765
760
|
/**
|
766
|
-
* @
|
761
|
+
* @param {{
|
762
|
+
* url:string;
|
763
|
+
* rpcKey?:string;
|
764
|
+
* signal?:AbortSignal;
|
765
|
+
* intercept?:(res:Response)=>void;
|
766
|
+
* }} param
|
767
|
+
*/
|
768
|
+
export function _testCreateRpcClientHttp(param) {
|
769
|
+
let helper = createRpcClientHelper({ rpcKey: param.rpcKey })
|
770
|
+
let writer = helper.writable.getWriter()
|
771
|
+
helper.readable.pipeTo(new WritableStream({
|
772
|
+
write(chunk) {
|
773
|
+
fetch(param.url, {
|
774
|
+
method: 'POST',
|
775
|
+
signal: param.signal,
|
776
|
+
// @ts-ignore
|
777
|
+
duplex: 'half',
|
778
|
+
body: new ReadableStream({
|
779
|
+
async pull(controller) {
|
780
|
+
controller.enqueue(chunk.slice(0, 10))
|
781
|
+
await sleep(1000)
|
782
|
+
controller.enqueue(chunk.slice(10))
|
783
|
+
controller.close()
|
784
|
+
}
|
785
|
+
}),
|
786
|
+
}).then(res => {
|
787
|
+
if (param.intercept) {
|
788
|
+
param.intercept(res)
|
789
|
+
}
|
790
|
+
res.body.pipeThrough(processPackets()).pipeTo(new WritableStream({
|
791
|
+
async write(chunk) {
|
792
|
+
await writer.write(chunk)
|
793
|
+
}
|
794
|
+
})).catch((e) => {
|
795
|
+
helper.reject(e)
|
796
|
+
})
|
797
|
+
}).catch(e => {
|
798
|
+
helper.reject(e)
|
799
|
+
})
|
800
|
+
}
|
801
|
+
})).catch((err) => helper.reject(err))
|
802
|
+
return createRPCProxy(helper.apiInvoke)
|
803
|
+
}
|
804
|
+
|
805
|
+
/**
|
767
806
|
* @param {{
|
768
807
|
* port:MessagePort;
|
769
808
|
* rpcKey:string;
|
770
|
-
* extension:
|
809
|
+
* extension: object;
|
771
810
|
* logger?:(msg:string)=>void;
|
772
811
|
* }} param
|
773
812
|
*/
|
@@ -789,11 +828,10 @@ export function createRpcServerMessagePort(param) {
|
|
789
828
|
|
790
829
|
/**
|
791
830
|
* @import {Electron} from './types.js'
|
792
|
-
* @template T
|
793
831
|
* @param {{
|
794
832
|
* port:Electron.MessagePortMain;
|
795
833
|
* rpcKey:string;
|
796
|
-
* extension:
|
834
|
+
* extension: object;
|
797
835
|
* logger?:(msg:string)=>void;
|
798
836
|
* }} param
|
799
837
|
*/
|
@@ -835,34 +873,36 @@ export function createRpcClientMessagePort(param) {
|
|
835
873
|
|
836
874
|
/**
|
837
875
|
* @param {string} text
|
838
|
-
* @returns
|
839
876
|
*/
|
840
877
|
export function base64decode(text) {
|
841
|
-
const
|
842
|
-
const
|
843
|
-
|
844
|
-
|
878
|
+
const binaryString = atob(text)
|
879
|
+
const len = binaryString.length
|
880
|
+
const bytes = new Uint8Array(len)
|
881
|
+
for (let i = 0; i < len; i++) {
|
882
|
+
bytes[i] = binaryString.charCodeAt(i)
|
883
|
+
}
|
884
|
+
return bytes
|
845
885
|
}
|
846
886
|
|
847
887
|
/**
|
848
888
|
* @param {Uint8Array<ArrayBuffer>} buffer
|
849
|
-
* @returns
|
850
889
|
*/
|
851
|
-
export function base64encode(buffer
|
852
|
-
|
853
|
-
|
854
|
-
|
890
|
+
export function base64encode(buffer) {
|
891
|
+
const CHUNK_SZ = 0x8000
|
892
|
+
const chars = []
|
893
|
+
for (let i = 0; i < buffer.length; i += CHUNK_SZ) {
|
894
|
+
const chunk = buffer.subarray(i, i + CHUNK_SZ)
|
895
|
+
chars.push(String.fromCharCode.apply(null, chunk))
|
855
896
|
}
|
856
|
-
return
|
897
|
+
return btoa(chars.join(''))
|
857
898
|
}
|
858
899
|
|
859
900
|
/**
|
860
901
|
* @import {chrome as Chrome} from './types.js'
|
861
|
-
* @template T
|
862
902
|
* @param {{
|
863
903
|
* chrome:Chrome;
|
864
904
|
* key: string;
|
865
|
-
* extension:
|
905
|
+
* extension: {messageSender:Chrome.runtime.MessageSender;};
|
866
906
|
* logger?:(msg:string)=>void;
|
867
907
|
* }} param
|
868
908
|
*/
|
@@ -872,6 +912,7 @@ export function createRpcServerChromeExtensions(param) {
|
|
872
912
|
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
|
873
913
|
if (request.action === param.key) {
|
874
914
|
let tabId = sender.tab?.id
|
915
|
+
param.extension.messageSender = sender
|
875
916
|
let { keyServer, keyClient } = request.data
|
876
917
|
let helper = createRpcServerHelper({
|
877
918
|
rpcKey: '', extension: param.extension, async: true, logger: param.logger,
|
package/src/lib.test.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { test } from 'node:test'
|
2
2
|
import { deepStrictEqual, fail, ok, strictEqual } from 'node:assert'
|
3
|
-
import { createRpcClientHttp, createRpcClientWebSocket, sleep, Uint8Array_from } from './lib.js'
|
3
|
+
import { _testCreateRpcClientHttp, createRpcClientHttp, createRpcClientWebSocket, sleep, Uint8Array_from } from './lib.js'
|
4
4
|
import { createServer } from 'node:http'
|
5
5
|
import { WebSocketServer } from 'ws'
|
6
6
|
import Koa from 'koa'
|
@@ -292,6 +292,9 @@ test('测试RPC调用-KoaRouter-AsyncLocalStorage', async () => {
|
|
292
292
|
hello: async function (/** @type {string} */ name) {
|
293
293
|
let ctx = this.asyncLocalStorage.getStore()
|
294
294
|
strictEqual(ctx.path, '/abc')
|
295
|
+
await sleep(100)
|
296
|
+
ctx = this.asyncLocalStorage.getStore()
|
297
|
+
strictEqual(ctx.path, '/abc')
|
295
298
|
return `hello ${name}`
|
296
299
|
},
|
297
300
|
}
|
@@ -320,7 +323,7 @@ test('测试RPC调用-KoaRouter-AsyncLocalStorage', async () => {
|
|
320
323
|
await sleep(100)
|
321
324
|
|
322
325
|
/** @type{typeof extension} */
|
323
|
-
let client =
|
326
|
+
let client = _testCreateRpcClientHttp({
|
324
327
|
url: `http://127.0.0.1:9000/abc`,
|
325
328
|
rpcKey: 'abc',
|
326
329
|
signal: ac.signal,
|
package/src/server.js
CHANGED
@@ -3,8 +3,8 @@ import { createRpcServerHelper } from "./lib.js"
|
|
3
3
|
import { AsyncLocalStorage } from "node:async_hooks"
|
4
4
|
|
5
5
|
/**
|
6
|
+
* @import { IncomingMessage } from "node:http"
|
6
7
|
* @import {WebSocketServer} from 'ws'
|
7
|
-
* @import {ExtensionApi} from './types.js'
|
8
8
|
*/
|
9
9
|
|
10
10
|
export { createRpcServerHelper }
|
@@ -19,14 +19,13 @@ export { createRpcServerHelper }
|
|
19
19
|
* path: string;
|
20
20
|
* wss: WebSocketServer;
|
21
21
|
* rpcKey:string;
|
22
|
-
* extension:
|
22
|
+
* extension: {asyncLocalStorage:AsyncLocalStorage<IncomingMessage>;};
|
23
23
|
* logger?:(msg:string)=>void;
|
24
24
|
* }} param
|
25
25
|
*/
|
26
26
|
export function createRpcServerWebSocket(param) {
|
27
|
-
|
28
|
-
|
29
|
-
}
|
27
|
+
let asyncLocalStorage = param.extension.asyncLocalStorage
|
28
|
+
if (!asyncLocalStorage) { asyncLocalStorage = new AsyncLocalStorage() }
|
30
29
|
param.wss.on('connection', (ws, request) => {
|
31
30
|
let url = request.url
|
32
31
|
if (url != param.path) {
|
@@ -47,6 +46,7 @@ export function createRpcServerWebSocket(param) {
|
|
47
46
|
if (writer.desiredSize <= 0) {
|
48
47
|
ws.pause()
|
49
48
|
}
|
49
|
+
asyncLocalStorage.enterWith(request)
|
50
50
|
await writer.write(buffer)
|
51
51
|
ws.resume()
|
52
52
|
})
|
@@ -60,23 +60,27 @@ export function createRpcServerWebSocket(param) {
|
|
60
60
|
}
|
61
61
|
|
62
62
|
/**
|
63
|
-
* @template T
|
64
63
|
* @param {{
|
65
64
|
* path: string;
|
66
65
|
* router: Router<any, {}>;
|
67
66
|
* rpcKey?:string;
|
68
67
|
* logger?:(msg:string)=>void;
|
69
|
-
* extension:
|
68
|
+
* extension: {asyncLocalStorage:AsyncLocalStorage;};
|
70
69
|
* }} param
|
71
70
|
*/
|
72
71
|
export function createRpcServerKoaRouter(param) {
|
73
|
-
|
74
|
-
|
75
|
-
}
|
72
|
+
let asyncLocalStorage = param.extension.asyncLocalStorage
|
73
|
+
if (!asyncLocalStorage) { asyncLocalStorage = new AsyncLocalStorage() }
|
76
74
|
param.router.post(param.path, async (ctx) => {
|
77
|
-
|
75
|
+
asyncLocalStorage.enterWith(ctx)
|
76
|
+
let helper = createRpcServerHelper({ rpcKey: param.rpcKey, extension: param.extension, logger: param.logger })
|
78
77
|
let a = Readable.toWeb(ctx.req)
|
79
|
-
await a.
|
78
|
+
await a.pipeThrough(new TransformStream({
|
79
|
+
async transform(chunk, controller) {
|
80
|
+
asyncLocalStorage.enterWith(ctx)
|
81
|
+
controller.enqueue(chunk)
|
82
|
+
}
|
83
|
+
})).pipeTo(helper.writable)
|
80
84
|
ctx.status = 200
|
81
85
|
ctx.response.set({
|
82
86
|
'Connection': 'keep-alive',
|
package/src/types.ts
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
2
|
-
|
3
|
-
export type ExtensionApi<T> = { asyncLocalStorage?: AsyncLocalStorage<T> } & object;
|
4
|
-
|
5
|
-
|
6
1
|
export type RPC_TYPE_CALL = 0xdf68f4cb
|
7
2
|
export type RPC_TYPE_RETURN = 0x68b17581
|
8
3
|
export type RPC_TYPE_CALLBACK = 0x8d65e5cc
|