@dxos/edge-client 0.6.12-main.5cc132e → 0.6.12-main.78ddbdf
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/dist/lib/browser/chunk-ZWJXA37R.mjs +113 -0
- package/dist/lib/browser/chunk-ZWJXA37R.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +57 -157
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +122 -0
- package/dist/lib/browser/testing/index.mjs.map +7 -0
- package/dist/lib/node/chunk-ANV2HBEH.cjs +136 -0
- package/dist/lib/node/chunk-ANV2HBEH.cjs.map +7 -0
- package/dist/lib/node/index.cjs +56 -154
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +152 -0
- package/dist/lib/node/testing/index.cjs.map +7 -0
- package/dist/lib/node-esm/chunk-HNVT57AU.mjs +115 -0
- package/dist/lib/node-esm/chunk-HNVT57AU.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +58 -157
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +123 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/defs.d.ts.map +1 -1
- package/dist/types/src/edge-client.d.ts +3 -2
- package/dist/types/src/edge-client.d.ts.map +1 -1
- package/dist/types/src/errors.d.ts +4 -1
- package/dist/types/src/errors.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/protocol.d.ts +2 -2
- package/dist/types/src/protocol.d.ts.map +1 -1
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/test-utils.d.ts +20 -0
- package/dist/types/src/testing/test-utils.d.ts.map +1 -0
- package/package.json +24 -13
- package/src/defs.ts +2 -3
- package/src/edge-client.test.ts +8 -5
- package/src/edge-client.ts +17 -8
- package/src/errors.ts +8 -2
- package/src/index.ts +1 -0
- package/src/protocol.ts +2 -2
- package/src/testing/index.ts +5 -0
- package/src/testing/test-utils.ts +111 -0
- package/src/websocket.test.ts +6 -5
- package/dist/types/src/test-utils.d.ts +0 -11
- package/dist/types/src/test-utils.d.ts.map +0 -1
- package/src/test-utils.ts +0 -49
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
protocol,
|
|
4
|
+
toUint8Array
|
|
5
|
+
} from "../chunk-HNVT57AU.mjs";
|
|
6
|
+
|
|
7
|
+
// packages/core/mesh/edge-client/src/testing/test-utils.ts
|
|
8
|
+
import WebSocket from "isomorphic-ws";
|
|
9
|
+
import { Trigger } from "@dxos/async";
|
|
10
|
+
import { log } from "@dxos/log";
|
|
11
|
+
import { buf } from "@dxos/protocols/buf";
|
|
12
|
+
import { MessageSchema, TextMessageSchema } from "@dxos/protocols/buf/dxos/edge/messenger_pb";
|
|
13
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/core/mesh/edge-client/src/testing/test-utils.ts";
|
|
14
|
+
var DEFAULT_PORT = 8080;
|
|
15
|
+
var createTestEdgeWsServer = async (port = DEFAULT_PORT, params) => {
|
|
16
|
+
const server = new WebSocket.Server({
|
|
17
|
+
port,
|
|
18
|
+
verifyClient: createConnectionDelayHandler(params)
|
|
19
|
+
});
|
|
20
|
+
let connection;
|
|
21
|
+
const messageSink = [];
|
|
22
|
+
const closeTrigger = new Trigger();
|
|
23
|
+
const sendResponseMessage = createResponseSender(() => connection);
|
|
24
|
+
server.on("connection", (ws) => {
|
|
25
|
+
connection = ws;
|
|
26
|
+
ws.on("error", (err) => log.catch(err, void 0, {
|
|
27
|
+
F: __dxlog_file,
|
|
28
|
+
L: 34,
|
|
29
|
+
S: void 0,
|
|
30
|
+
C: (f, a) => f(...a)
|
|
31
|
+
}));
|
|
32
|
+
ws.on("message", async (data) => {
|
|
33
|
+
if (String(data) === "__ping__") {
|
|
34
|
+
ws.send("__pong__");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const { request, requestPayload } = await decodeRequest(params, data);
|
|
38
|
+
if (params?.messageHandler) {
|
|
39
|
+
const responsePayload = await params.messageHandler(requestPayload);
|
|
40
|
+
if (responsePayload && connection) {
|
|
41
|
+
sendResponseMessage(request, responsePayload);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
log("message", {
|
|
45
|
+
payload: requestPayload
|
|
46
|
+
}, {
|
|
47
|
+
F: __dxlog_file,
|
|
48
|
+
L: 47,
|
|
49
|
+
S: void 0,
|
|
50
|
+
C: (f, a) => f(...a)
|
|
51
|
+
});
|
|
52
|
+
messageSink.push(requestPayload);
|
|
53
|
+
});
|
|
54
|
+
ws.on("close", () => {
|
|
55
|
+
connection = void 0;
|
|
56
|
+
closeTrigger.wake();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
return {
|
|
60
|
+
server,
|
|
61
|
+
messageSink,
|
|
62
|
+
endpoint: `ws://localhost:${port}`,
|
|
63
|
+
cleanup: () => server.close(),
|
|
64
|
+
currentConnection: () => connection,
|
|
65
|
+
sendResponseMessage,
|
|
66
|
+
closeConnection: () => {
|
|
67
|
+
closeTrigger.reset();
|
|
68
|
+
connection.close(1011);
|
|
69
|
+
return closeTrigger.wait();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
var createConnectionDelayHandler = (params) => {
|
|
74
|
+
return (_, callback) => {
|
|
75
|
+
if (params?.admitConnection) {
|
|
76
|
+
log("delaying edge connection admission", void 0, {
|
|
77
|
+
F: __dxlog_file,
|
|
78
|
+
L: 75,
|
|
79
|
+
S: void 0,
|
|
80
|
+
C: (f, a) => f(...a)
|
|
81
|
+
});
|
|
82
|
+
void params.admitConnection.wait().then(() => {
|
|
83
|
+
callback(true);
|
|
84
|
+
log("edge connection admitted", void 0, {
|
|
85
|
+
F: __dxlog_file,
|
|
86
|
+
L: 78,
|
|
87
|
+
S: void 0,
|
|
88
|
+
C: (f, a) => f(...a)
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
callback(true);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
var createResponseSender = (connection) => {
|
|
97
|
+
return (request, responsePayload) => {
|
|
98
|
+
const recipient = request.source;
|
|
99
|
+
connection().send(buf.toBinary(MessageSchema, buf.create(MessageSchema, {
|
|
100
|
+
source: {
|
|
101
|
+
identityKey: recipient.identityKey,
|
|
102
|
+
peerKey: recipient.peerKey
|
|
103
|
+
},
|
|
104
|
+
serviceId: request.serviceId,
|
|
105
|
+
payload: {
|
|
106
|
+
value: responsePayload
|
|
107
|
+
}
|
|
108
|
+
})));
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
var decodeRequest = async (params, data) => {
|
|
112
|
+
const request = buf.fromBinary(MessageSchema, await toUint8Array(data));
|
|
113
|
+
const requestPayload = params?.payloadDecoder ? params.payloadDecoder(request.payload.value) : protocol.getPayload(request, TextMessageSchema);
|
|
114
|
+
return {
|
|
115
|
+
request,
|
|
116
|
+
requestPayload
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
export {
|
|
120
|
+
DEFAULT_PORT,
|
|
121
|
+
createTestEdgeWsServer
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/testing/test-utils.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport WebSocket from 'isomorphic-ws';\n\nimport { Trigger } from '@dxos/async';\nimport { log } from '@dxos/log';\nimport { buf } from '@dxos/protocols/buf';\nimport { MessageSchema, TextMessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';\n\nimport { protocol } from '../defs';\nimport { toUint8Array } from '../protocol';\n\nexport const DEFAULT_PORT = 8080;\n\ntype TestEdgeWsServerParams = {\n admitConnection?: Trigger;\n payloadDecoder?: (payload: Uint8Array) => any;\n messageHandler?: (payload: any) => Promise<Uint8Array | undefined>;\n};\n\nexport const createTestEdgeWsServer = async (port = DEFAULT_PORT, params?: TestEdgeWsServerParams) => {\n const server = new WebSocket.Server({ port, verifyClient: createConnectionDelayHandler(params) });\n\n let connection: WebSocket | undefined;\n\n const messageSink: any[] = [];\n const closeTrigger = new Trigger();\n const sendResponseMessage = createResponseSender(() => connection!);\n\n server.on('connection', (ws) => {\n connection = ws;\n ws.on('error', (err) => log.catch(err));\n ws.on('message', async (data) => {\n if (String(data) === '__ping__') {\n ws.send('__pong__');\n return;\n }\n const { request, requestPayload } = await decodeRequest(params, data);\n if (params?.messageHandler) {\n const responsePayload = await params.messageHandler(requestPayload);\n if (responsePayload && connection) {\n sendResponseMessage(request, responsePayload);\n }\n }\n log('message', { payload: requestPayload });\n messageSink.push(requestPayload);\n });\n\n ws.on('close', () => {\n connection = undefined;\n closeTrigger.wake();\n });\n });\n\n return {\n server,\n messageSink,\n endpoint: `ws://localhost:${port}`,\n cleanup: () => server.close(),\n currentConnection: () => connection,\n sendResponseMessage,\n closeConnection: () => {\n closeTrigger.reset();\n connection!.close(1011);\n return closeTrigger.wait();\n },\n };\n};\n\nconst createConnectionDelayHandler = (params: TestEdgeWsServerParams | undefined) => {\n return (_: any, callback: (admit: boolean) => void) => {\n if (params?.admitConnection) {\n log('delaying edge connection admission');\n void params.admitConnection.wait().then(() => {\n callback(true);\n log('edge connection admitted');\n });\n } else {\n callback(true);\n }\n };\n};\n\nconst createResponseSender = (connection: () => WebSocket) => {\n return (request: Message, responsePayload: Uint8Array) => {\n const recipient = request.source!;\n connection().send(\n buf.toBinary(\n MessageSchema,\n buf.create(MessageSchema, {\n source: {\n identityKey: recipient.identityKey,\n peerKey: recipient.peerKey,\n },\n serviceId: request.serviceId!,\n payload: { value: responsePayload },\n }),\n ),\n );\n };\n};\n\nconst decodeRequest = async (params: TestEdgeWsServerParams | undefined, data: any) => {\n const request = buf.fromBinary(MessageSchema, await toUint8Array(data));\n const requestPayload = params?.payloadDecoder\n ? params.payloadDecoder(request.payload!.value!)\n : protocol.getPayload(request, TextMessageSchema);\n return { request, requestPayload };\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;AAIA,OAAOA,eAAe;AAEtB,SAASC,eAAe;AACxB,SAASC,WAAW;AACpB,SAASC,WAAW;AACpB,SAASC,eAAeC,yBAAuC;;AAKxD,IAAMC,eAAe;AAQrB,IAAMC,yBAAyB,OAAOC,OAAOF,cAAcG,WAAAA;AAChE,QAAMC,SAAS,IAAIC,UAAUC,OAAO;IAAEJ;IAAMK,cAAcC,6BAA6BL,MAAAA;EAAQ,CAAA;AAE/F,MAAIM;AAEJ,QAAMC,cAAqB,CAAA;AAC3B,QAAMC,eAAe,IAAIC,QAAAA;AACzB,QAAMC,sBAAsBC,qBAAqB,MAAML,UAAAA;AAEvDL,SAAOW,GAAG,cAAc,CAACC,OAAAA;AACvBP,iBAAaO;AACbA,OAAGD,GAAG,SAAS,CAACE,QAAQC,IAAIC,MAAMF,KAAAA,QAAAA;;;;;;AAClCD,OAAGD,GAAG,WAAW,OAAOK,SAAAA;AACtB,UAAIC,OAAOD,IAAAA,MAAU,YAAY;AAC/BJ,WAAGM,KAAK,UAAA;AACR;MACF;AACA,YAAM,EAAEC,SAASC,eAAc,IAAK,MAAMC,cAActB,QAAQiB,IAAAA;AAChE,UAAIjB,QAAQuB,gBAAgB;AAC1B,cAAMC,kBAAkB,MAAMxB,OAAOuB,eAAeF,cAAAA;AACpD,YAAIG,mBAAmBlB,YAAY;AACjCI,8BAAoBU,SAASI,eAAAA;QAC/B;MACF;AACAT,UAAI,WAAW;QAAEU,SAASJ;MAAe,GAAA;;;;;;AACzCd,kBAAYmB,KAAKL,cAAAA;IACnB,CAAA;AAEAR,OAAGD,GAAG,SAAS,MAAA;AACbN,mBAAaqB;AACbnB,mBAAaoB,KAAI;IACnB,CAAA;EACF,CAAA;AAEA,SAAO;IACL3B;IACAM;IACAsB,UAAU,kBAAkB9B,IAAAA;IAC5B+B,SAAS,MAAM7B,OAAO8B,MAAK;IAC3BC,mBAAmB,MAAM1B;IACzBI;IACAuB,iBAAiB,MAAA;AACfzB,mBAAa0B,MAAK;AAClB5B,iBAAYyB,MAAM,IAAA;AAClB,aAAOvB,aAAa2B,KAAI;IAC1B;EACF;AACF;AAEA,IAAM9B,+BAA+B,CAACL,WAAAA;AACpC,SAAO,CAACoC,GAAQC,aAAAA;AACd,QAAIrC,QAAQsC,iBAAiB;AAC3BvB,UAAI,sCAAA,QAAA;;;;;;AACJ,WAAKf,OAAOsC,gBAAgBH,KAAI,EAAGI,KAAK,MAAA;AACtCF,iBAAS,IAAA;AACTtB,YAAI,4BAAA,QAAA;;;;;;MACN,CAAA;IACF,OAAO;AACLsB,eAAS,IAAA;IACX;EACF;AACF;AAEA,IAAM1B,uBAAuB,CAACL,eAAAA;AAC5B,SAAO,CAACc,SAAkBI,oBAAAA;AACxB,UAAMgB,YAAYpB,QAAQqB;AAC1BnC,eAAAA,EAAaa,KACXuB,IAAIC,SACFC,eACAF,IAAIG,OAAOD,eAAe;MACxBH,QAAQ;QACNK,aAAaN,UAAUM;QACvBC,SAASP,UAAUO;MACrB;MACAC,WAAW5B,QAAQ4B;MACnBvB,SAAS;QAAEwB,OAAOzB;MAAgB;IACpC,CAAA,CAAA,CAAA;EAGN;AACF;AAEA,IAAMF,gBAAgB,OAAOtB,QAA4CiB,SAAAA;AACvE,QAAMG,UAAUsB,IAAIQ,WAAWN,eAAe,MAAMO,aAAalC,IAAAA,CAAAA;AACjE,QAAMI,iBAAiBrB,QAAQoD,iBAC3BpD,OAAOoD,eAAehC,QAAQK,QAASwB,KAAK,IAC5CI,SAASC,WAAWlC,SAASmC,iBAAAA;AACjC,SAAO;IAAEnC;IAASC;EAAe;AACnC;",
|
|
6
|
+
"names": ["WebSocket", "Trigger", "log", "buf", "MessageSchema", "TextMessageSchema", "DEFAULT_PORT", "createTestEdgeWsServer", "port", "params", "server", "WebSocket", "Server", "verifyClient", "createConnectionDelayHandler", "connection", "messageSink", "closeTrigger", "Trigger", "sendResponseMessage", "createResponseSender", "on", "ws", "err", "log", "catch", "data", "String", "send", "request", "requestPayload", "decodeRequest", "messageHandler", "responsePayload", "payload", "push", "undefined", "wake", "endpoint", "cleanup", "close", "currentConnection", "closeConnection", "reset", "wait", "_", "callback", "admitConnection", "then", "recipient", "source", "buf", "toBinary", "MessageSchema", "create", "identityKey", "peerKey", "serviceId", "value", "fromBinary", "toUint8Array", "payloadDecoder", "protocol", "getPayload", "TextMessageSchema"]
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../../src/defs.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,QAAQ,UAA+F,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
|
4
4
|
import { type Protocol } from './protocol';
|
|
5
5
|
export type MessageListener = (message: Message) => void | Promise<void>;
|
|
6
6
|
export interface EdgeConnection extends Required<Lifecycle> {
|
|
7
|
+
connected: Event;
|
|
7
8
|
reconnect: Event;
|
|
8
9
|
get info(): any;
|
|
9
10
|
get identityKey(): string;
|
|
@@ -28,10 +29,10 @@ export declare class EdgeClient extends Resource implements EdgeConnection {
|
|
|
28
29
|
private _identityKey;
|
|
29
30
|
private _peerKey;
|
|
30
31
|
private readonly _config;
|
|
31
|
-
reconnect: Event<void>;
|
|
32
|
+
readonly reconnect: Event<void>;
|
|
33
|
+
readonly connected: Event<void>;
|
|
32
34
|
private readonly _persistentLifecycle;
|
|
33
35
|
private readonly _listeners;
|
|
34
|
-
private readonly _protocol;
|
|
35
36
|
private _ready;
|
|
36
37
|
private _ws?;
|
|
37
38
|
private _keepaliveCtx?;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge-client.d.ts","sourceRoot":"","sources":["../../../src/edge-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAW,KAAK,EAAoD,MAAM,aAAa,CAAC;AAC/F,OAAO,EAA2B,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"edge-client.d.ts","sourceRoot":"","sources":["../../../src/edge-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAW,KAAK,EAAoD,MAAM,aAAa,CAAC;AAC/F,OAAO,EAA2B,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlF,OAAO,EAAE,KAAK,OAAO,EAAiB,MAAM,4CAA4C,CAAC;AAKzF,OAAO,EAAE,KAAK,QAAQ,EAAgB,MAAM,YAAY,CAAC;AAKzD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEzE,MAAM,WAAW,cAAe,SAAQ,QAAQ,CAAC,SAAS,CAAC;IACzD,SAAS,EAAE,KAAK,CAAC;IACjB,SAAS,EAAE,KAAK,CAAC;IAEjB,IAAI,IAAI,IAAI,GAAG,CAAC;IAChB,IAAI,WAAW,IAAI,MAAM,CAAC;IAC1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,MAAM,IAAI,OAAO,CAAC;IACtB,WAAW,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI,CAAC;IACnD,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,qBAAa,UAAW,SAAQ,QAAS,YAAW,cAAc;IAgB9D,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAjB1B,SAAgB,SAAS,cAAe;IACxC,SAAgB,SAAS,cAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAIlC;IAEH,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8B;IACzD,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,GAAG,CAAC,CAAwB;IACpC,OAAO,CAAC,aAAa,CAAC,CAAsB;IAC5C,OAAO,CAAC,iBAAiB,CAAC,CAAsB;gBAGtC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EACP,OAAO,EAAE,eAAe;IAM3C,IAAW,IAAI;;;;MAMd;IAED,IAAI,WAAW,WAEd;IAED,IAAI,OAAO,WAEV;IAED,WAAW,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE;IAMvE,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IAKzD;;OAEG;cACsB,KAAK;IAO9B;;OAEG;cACsB,MAAM;YAKjB,cAAc;YAsDd,eAAe;IA0B7B;;;OAGG;IACU,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBlD,OAAO,CAAC,YAAY;CAcrB"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export declare class
|
|
1
|
+
export declare class EdgeConnectionClosedError extends Error {
|
|
2
|
+
constructor();
|
|
3
|
+
}
|
|
4
|
+
export declare class EdgeIdentityChangedError extends Error {
|
|
2
5
|
constructor();
|
|
3
6
|
}
|
|
4
7
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"AAIA,qBAAa,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"AAIA,qBAAa,yBAA0B,SAAQ,KAAK;;CAInD;AAED,qBAAa,wBAAyB,SAAQ,KAAK;;CAIlD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,4CAA4C,CAAC;AAE3D,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAIA,cAAc,4CAA4C,CAAC;AAE3D,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { buf } from '@dxos/protocols/buf';
|
|
2
|
-
import { type Message, type
|
|
3
|
-
export type PeerData =
|
|
2
|
+
import { type Message, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
3
|
+
export type PeerData = buf.MessageInitShape<typeof PeerSchema>;
|
|
4
4
|
export declare const getTypename: (typeName: string) => string;
|
|
5
5
|
/**
|
|
6
6
|
* NOTE: The type registry should be extended with all message types.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/protocol.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAU,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAiB,KAAK,
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/protocol.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,GAAG,EAAU,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,KAAK,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,4CAA4C,CAAC;AAG1G,MAAM,MAAM,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC,OAAO,UAAU,CAAC,CAAC;AAE/D,eAAO,MAAM,WAAW,aAAc,MAAM,WAAsC,CAAC;AAEnF;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;gBAEjC,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE;IAIpC,IAAI,YAAY,IAAI,GAAG,CAAC,QAAQ,CAE/B;IAED,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,GAAG;IAQ7B;;OAEG;IACH,UAAU,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC;IAa9F;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS;IASpD;;OAEG;IACH,aAAa,CAAC,IAAI,SAAS,GAAG,CAAC,WAAW,EACxC,IAAI,EAAE,IAAI,EACV,EACE,MAAM,EACN,MAAM,EACN,OAAO,EACP,SAAS,GACV,EAAE;QACD,MAAM,CAAC,EAAE,QAAQ,CAAC;QAClB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;QACpB,OAAO,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB;CAUJ;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,SAAgB,GAAG,KAAG,OAAO,CAAC,UAAU,CAYhE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/testing/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import WebSocket from 'isomorphic-ws';
|
|
2
|
+
import { Trigger } from '@dxos/async';
|
|
3
|
+
import { type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
4
|
+
export declare const DEFAULT_PORT = 8080;
|
|
5
|
+
type TestEdgeWsServerParams = {
|
|
6
|
+
admitConnection?: Trigger;
|
|
7
|
+
payloadDecoder?: (payload: Uint8Array) => any;
|
|
8
|
+
messageHandler?: (payload: any) => Promise<Uint8Array | undefined>;
|
|
9
|
+
};
|
|
10
|
+
export declare const createTestEdgeWsServer: (port?: number, params?: TestEdgeWsServerParams) => Promise<{
|
|
11
|
+
server: WebSocket.Server;
|
|
12
|
+
messageSink: any[];
|
|
13
|
+
endpoint: string;
|
|
14
|
+
cleanup: () => void;
|
|
15
|
+
currentConnection: () => WebSocket | undefined;
|
|
16
|
+
sendResponseMessage: (request: Message, responsePayload: Uint8Array) => void;
|
|
17
|
+
closeConnection: () => Promise<void>;
|
|
18
|
+
}>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../../src/testing/test-utils.ts"],"names":[],"mappings":"AAIA,OAAO,SAAS,MAAM,eAAe,CAAC;AAEtC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGtC,OAAO,EAAoC,KAAK,OAAO,EAAE,MAAM,4CAA4C,CAAC;AAK5G,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,KAAK,sBAAsB,GAAG;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,GAAG,CAAC;IAC9C,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;CACpE,CAAC;AAEF,eAAO,MAAM,sBAAsB,2BAAwC,sBAAsB;;;;;;mCAgE9E,OAAO,mBAAmB,UAAU;;EAjBtD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/edge-client",
|
|
3
|
-
"version": "0.6.12-main.
|
|
3
|
+
"version": "0.6.12-main.78ddbdf",
|
|
4
4
|
"description": "EDGE Client",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -14,11 +14,23 @@
|
|
|
14
14
|
"default": "./dist/lib/node-esm/index.mjs"
|
|
15
15
|
},
|
|
16
16
|
"types": "./dist/types/src/index.d.ts"
|
|
17
|
+
},
|
|
18
|
+
"./testing": {
|
|
19
|
+
"browser": "./dist/lib/browser/testing/index.mjs",
|
|
20
|
+
"node": {
|
|
21
|
+
"require": "./dist/lib/node/testing/index.cjs",
|
|
22
|
+
"default": "./dist/lib/node-esm/testing/index.mjs"
|
|
23
|
+
},
|
|
24
|
+
"types": "./dist/types/src/testing/index.d.ts"
|
|
17
25
|
}
|
|
18
26
|
},
|
|
19
27
|
"types": "dist/types/src/index.d.ts",
|
|
20
28
|
"typesVersions": {
|
|
21
|
-
"*": {
|
|
29
|
+
"*": {
|
|
30
|
+
"testing": [
|
|
31
|
+
"dist/types/src/testing/index.d.ts"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
22
34
|
},
|
|
23
35
|
"files": [
|
|
24
36
|
"dist",
|
|
@@ -26,21 +38,20 @@
|
|
|
26
38
|
"README.md"
|
|
27
39
|
],
|
|
28
40
|
"dependencies": {
|
|
29
|
-
"@bufbuild/protobuf": "^2.0.0",
|
|
30
41
|
"isomorphic-ws": "^5.0.0",
|
|
31
42
|
"ws": "^8.14.2",
|
|
32
|
-
"@dxos/async": "0.6.12-main.
|
|
33
|
-
"@dxos/context": "0.6.12-main.
|
|
34
|
-
"@dxos/debug": "0.6.12-main.
|
|
35
|
-
"@dxos/invariant": "0.6.12-main.
|
|
36
|
-
"@dxos/log": "0.6.12-main.
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
43
|
+
"@dxos/async": "0.6.12-main.78ddbdf",
|
|
44
|
+
"@dxos/context": "0.6.12-main.78ddbdf",
|
|
45
|
+
"@dxos/debug": "0.6.12-main.78ddbdf",
|
|
46
|
+
"@dxos/invariant": "0.6.12-main.78ddbdf",
|
|
47
|
+
"@dxos/log": "0.6.12-main.78ddbdf",
|
|
48
|
+
"@dxos/protocols": "0.6.12-main.78ddbdf",
|
|
49
|
+
"@dxos/node-std": "0.6.12-main.78ddbdf",
|
|
50
|
+
"@dxos/util": "0.6.12-main.78ddbdf"
|
|
40
51
|
},
|
|
41
52
|
"devDependencies": {
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
53
|
+
"@dxos/test-utils": "0.6.12-main.78ddbdf",
|
|
54
|
+
"@dxos/keys": "0.6.12-main.78ddbdf"
|
|
44
55
|
},
|
|
45
56
|
"publishConfig": {
|
|
46
57
|
"access": "public"
|
package/src/defs.ts
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { bufWkt } from '@dxos/protocols/buf';
|
|
7
6
|
import { SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
8
7
|
|
|
9
8
|
import { Protocol } from './protocol';
|
|
10
9
|
|
|
11
|
-
export const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, AnySchema]);
|
|
10
|
+
export const protocol = new Protocol([SwarmRequestSchema, SwarmResponseSchema, TextMessageSchema, bufWkt.AnySchema]);
|
package/src/edge-client.test.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { test, expect, describe } from 'vitest';
|
|
5
|
+
import { test, expect, describe, onTestFinished } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { PublicKey } from '@dxos/keys';
|
|
8
8
|
import { TextMessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
@@ -10,13 +10,15 @@ import { openAndClose } from '@dxos/test-utils';
|
|
|
10
10
|
|
|
11
11
|
import { protocol } from './defs';
|
|
12
12
|
import { EdgeClient } from './edge-client';
|
|
13
|
-
import {
|
|
13
|
+
import { createTestEdgeWsServer } from './testing';
|
|
14
14
|
|
|
15
15
|
describe('EdgeClient', () => {
|
|
16
16
|
const textMessage = (message: string) => protocol.createMessage(TextMessageSchema, { payload: { message } });
|
|
17
17
|
|
|
18
18
|
test('reconnects on error', async () => {
|
|
19
|
-
const {
|
|
19
|
+
const { closeConnection, endpoint, cleanup } = await createTestEdgeWsServer(8001);
|
|
20
|
+
onTestFinished(cleanup);
|
|
21
|
+
|
|
20
22
|
const id = PublicKey.random().toHex();
|
|
21
23
|
const client = new EdgeClient(id, id, { socketEndpoint: endpoint });
|
|
22
24
|
await openAndClose(client);
|
|
@@ -24,13 +26,14 @@ describe('EdgeClient', () => {
|
|
|
24
26
|
expect(client.isOpen).is.true;
|
|
25
27
|
|
|
26
28
|
const reconnected = client.reconnect.waitForCount(1);
|
|
27
|
-
await
|
|
29
|
+
await closeConnection();
|
|
28
30
|
await reconnected;
|
|
29
31
|
await expect(client.send(textMessage('Hello world 2'))).resolves.not.toThrow();
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
test('set identity reconnects', async () => {
|
|
33
|
-
const { endpoint } = await
|
|
35
|
+
const { endpoint, cleanup } = await createTestEdgeWsServer(8002);
|
|
36
|
+
onTestFinished(cleanup);
|
|
34
37
|
|
|
35
38
|
const id = PublicKey.random().toHex();
|
|
36
39
|
const client = new EdgeClient(id, id, { socketEndpoint: endpoint });
|
package/src/edge-client.ts
CHANGED
|
@@ -6,13 +6,12 @@ import WebSocket from 'isomorphic-ws';
|
|
|
6
6
|
|
|
7
7
|
import { Trigger, Event, scheduleTaskInterval, scheduleTask, TriggerState } from '@dxos/async';
|
|
8
8
|
import { Context, LifecycleState, Resource, type Lifecycle } from '@dxos/context';
|
|
9
|
-
import { invariant } from '@dxos/invariant';
|
|
10
9
|
import { log } from '@dxos/log';
|
|
11
10
|
import { buf } from '@dxos/protocols/buf';
|
|
12
11
|
import { type Message, MessageSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
13
12
|
|
|
14
13
|
import { protocol } from './defs';
|
|
15
|
-
import {
|
|
14
|
+
import { EdgeConnectionClosedError, EdgeIdentityChangedError } from './errors';
|
|
16
15
|
import { PersistentLifecycle } from './persistent-lifecycle';
|
|
17
16
|
import { type Protocol, toUint8Array } from './protocol';
|
|
18
17
|
|
|
@@ -22,6 +21,7 @@ const SIGNAL_KEEPALIVE_INTERVAL = 5_000;
|
|
|
22
21
|
export type MessageListener = (message: Message) => void | Promise<void>;
|
|
23
22
|
|
|
24
23
|
export interface EdgeConnection extends Required<Lifecycle> {
|
|
24
|
+
connected: Event;
|
|
25
25
|
reconnect: Event;
|
|
26
26
|
|
|
27
27
|
get info(): any;
|
|
@@ -43,7 +43,8 @@ export type MessengerConfig = {
|
|
|
43
43
|
* Messenger client.
|
|
44
44
|
*/
|
|
45
45
|
export class EdgeClient extends Resource implements EdgeConnection {
|
|
46
|
-
public reconnect = new Event();
|
|
46
|
+
public readonly reconnect = new Event();
|
|
47
|
+
public readonly connected = new Event();
|
|
47
48
|
private readonly _persistentLifecycle = new PersistentLifecycle({
|
|
48
49
|
start: async () => this._openWebSocket(),
|
|
49
50
|
stop: async () => this._closeWebSocket(),
|
|
@@ -51,7 +52,6 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
51
52
|
});
|
|
52
53
|
|
|
53
54
|
private readonly _listeners = new Set<MessageListener>();
|
|
54
|
-
private readonly _protocol: Protocol;
|
|
55
55
|
private _ready = new Trigger();
|
|
56
56
|
private _ws?: WebSocket = undefined;
|
|
57
57
|
private _keepaliveCtx?: Context = undefined;
|
|
@@ -63,7 +63,6 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
63
63
|
private readonly _config: MessengerConfig,
|
|
64
64
|
) {
|
|
65
65
|
super();
|
|
66
|
-
this._protocol = this._config.protocol ?? protocol;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
// TODO(burdon): Attach logging.
|
|
@@ -119,6 +118,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
119
118
|
this._ws.onopen = () => {
|
|
120
119
|
log('opened', this.info);
|
|
121
120
|
this._ready.wake();
|
|
121
|
+
this.connected.emit();
|
|
122
122
|
};
|
|
123
123
|
this._ws.onclose = () => {
|
|
124
124
|
log('closed', this.info);
|
|
@@ -170,7 +170,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
172
|
try {
|
|
173
|
-
this._ready.throw(new
|
|
173
|
+
this._ready.throw(this.isOpen ? new EdgeIdentityChangedError() : new EdgeConnectionClosedError());
|
|
174
174
|
this._ready.reset();
|
|
175
175
|
void this._keepaliveCtx?.dispose();
|
|
176
176
|
this._keepaliveCtx = undefined;
|
|
@@ -197,10 +197,19 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
197
197
|
*/
|
|
198
198
|
public async send(message: Message): Promise<void> {
|
|
199
199
|
if (this._ready.state !== TriggerState.RESOLVED) {
|
|
200
|
+
log('waiting for websocket to become ready');
|
|
200
201
|
await this._ready.wait({ timeout: this._config.timeout ?? DEFAULT_TIMEOUT });
|
|
201
202
|
}
|
|
202
|
-
|
|
203
|
-
|
|
203
|
+
if (!this._ws) {
|
|
204
|
+
throw new EdgeConnectionClosedError();
|
|
205
|
+
}
|
|
206
|
+
if (
|
|
207
|
+
message.source &&
|
|
208
|
+
(message.source.peerKey !== this._peerKey || message.source.identityKey !== this.identityKey)
|
|
209
|
+
) {
|
|
210
|
+
throw new EdgeIdentityChangedError();
|
|
211
|
+
}
|
|
212
|
+
|
|
204
213
|
log('sending...', { peerKey: this._peerKey, payload: protocol.getPayloadType(message) });
|
|
205
214
|
this._ws.send(buf.toBinary(MessageSchema, message));
|
|
206
215
|
}
|
package/src/errors.ts
CHANGED
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
export class
|
|
5
|
+
export class EdgeConnectionClosedError extends Error {
|
|
6
6
|
constructor() {
|
|
7
|
-
super('
|
|
7
|
+
super('Edge connection closed.');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class EdgeIdentityChangedError extends Error {
|
|
12
|
+
constructor() {
|
|
13
|
+
super('Edge identity changed.');
|
|
8
14
|
}
|
|
9
15
|
}
|
package/src/index.ts
CHANGED
package/src/protocol.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import { invariant } from '@dxos/invariant';
|
|
6
6
|
import { buf, bufWkt } from '@dxos/protocols/buf';
|
|
7
|
-
import { type Message, MessageSchema, type
|
|
7
|
+
import { type Message, MessageSchema, type PeerSchema } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
8
8
|
import { bufferToArray } from '@dxos/util';
|
|
9
9
|
|
|
10
|
-
export type PeerData =
|
|
10
|
+
export type PeerData = buf.MessageInitShape<typeof PeerSchema>;
|
|
11
11
|
|
|
12
12
|
export const getTypename = (typeName: string) => `type.googleapis.com/${typeName}`;
|
|
13
13
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import WebSocket from 'isomorphic-ws';
|
|
6
|
+
|
|
7
|
+
import { Trigger } from '@dxos/async';
|
|
8
|
+
import { log } from '@dxos/log';
|
|
9
|
+
import { buf } from '@dxos/protocols/buf';
|
|
10
|
+
import { MessageSchema, TextMessageSchema, type Message } from '@dxos/protocols/buf/dxos/edge/messenger_pb';
|
|
11
|
+
|
|
12
|
+
import { protocol } from '../defs';
|
|
13
|
+
import { toUint8Array } from '../protocol';
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_PORT = 8080;
|
|
16
|
+
|
|
17
|
+
type TestEdgeWsServerParams = {
|
|
18
|
+
admitConnection?: Trigger;
|
|
19
|
+
payloadDecoder?: (payload: Uint8Array) => any;
|
|
20
|
+
messageHandler?: (payload: any) => Promise<Uint8Array | undefined>;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const createTestEdgeWsServer = async (port = DEFAULT_PORT, params?: TestEdgeWsServerParams) => {
|
|
24
|
+
const server = new WebSocket.Server({ port, verifyClient: createConnectionDelayHandler(params) });
|
|
25
|
+
|
|
26
|
+
let connection: WebSocket | undefined;
|
|
27
|
+
|
|
28
|
+
const messageSink: any[] = [];
|
|
29
|
+
const closeTrigger = new Trigger();
|
|
30
|
+
const sendResponseMessage = createResponseSender(() => connection!);
|
|
31
|
+
|
|
32
|
+
server.on('connection', (ws) => {
|
|
33
|
+
connection = ws;
|
|
34
|
+
ws.on('error', (err) => log.catch(err));
|
|
35
|
+
ws.on('message', async (data) => {
|
|
36
|
+
if (String(data) === '__ping__') {
|
|
37
|
+
ws.send('__pong__');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const { request, requestPayload } = await decodeRequest(params, data);
|
|
41
|
+
if (params?.messageHandler) {
|
|
42
|
+
const responsePayload = await params.messageHandler(requestPayload);
|
|
43
|
+
if (responsePayload && connection) {
|
|
44
|
+
sendResponseMessage(request, responsePayload);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
log('message', { payload: requestPayload });
|
|
48
|
+
messageSink.push(requestPayload);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
ws.on('close', () => {
|
|
52
|
+
connection = undefined;
|
|
53
|
+
closeTrigger.wake();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
server,
|
|
59
|
+
messageSink,
|
|
60
|
+
endpoint: `ws://localhost:${port}`,
|
|
61
|
+
cleanup: () => server.close(),
|
|
62
|
+
currentConnection: () => connection,
|
|
63
|
+
sendResponseMessage,
|
|
64
|
+
closeConnection: () => {
|
|
65
|
+
closeTrigger.reset();
|
|
66
|
+
connection!.close(1011);
|
|
67
|
+
return closeTrigger.wait();
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const createConnectionDelayHandler = (params: TestEdgeWsServerParams | undefined) => {
|
|
73
|
+
return (_: any, callback: (admit: boolean) => void) => {
|
|
74
|
+
if (params?.admitConnection) {
|
|
75
|
+
log('delaying edge connection admission');
|
|
76
|
+
void params.admitConnection.wait().then(() => {
|
|
77
|
+
callback(true);
|
|
78
|
+
log('edge connection admitted');
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
callback(true);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const createResponseSender = (connection: () => WebSocket) => {
|
|
87
|
+
return (request: Message, responsePayload: Uint8Array) => {
|
|
88
|
+
const recipient = request.source!;
|
|
89
|
+
connection().send(
|
|
90
|
+
buf.toBinary(
|
|
91
|
+
MessageSchema,
|
|
92
|
+
buf.create(MessageSchema, {
|
|
93
|
+
source: {
|
|
94
|
+
identityKey: recipient.identityKey,
|
|
95
|
+
peerKey: recipient.peerKey,
|
|
96
|
+
},
|
|
97
|
+
serviceId: request.serviceId!,
|
|
98
|
+
payload: { value: responsePayload },
|
|
99
|
+
}),
|
|
100
|
+
),
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const decodeRequest = async (params: TestEdgeWsServerParams | undefined, data: any) => {
|
|
106
|
+
const request = buf.fromBinary(MessageSchema, await toUint8Array(data));
|
|
107
|
+
const requestPayload = params?.payloadDecoder
|
|
108
|
+
? params.payloadDecoder(request.payload!.value!)
|
|
109
|
+
: protocol.getPayload(request, TextMessageSchema);
|
|
110
|
+
return { request, requestPayload };
|
|
111
|
+
};
|
package/src/websocket.test.ts
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import WebSocket from 'isomorphic-ws';
|
|
6
|
-
import { describe, expect, test } from 'vitest';
|
|
6
|
+
import { describe, expect, test, onTestFinished } from 'vitest';
|
|
7
7
|
|
|
8
8
|
import { Trigger, TriggerState } from '@dxos/async';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { createTestEdgeWsServer } from './testing';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
describe.skip('WebSocket', () => {
|
|
12
|
+
describe('WebSocket', () => {
|
|
14
13
|
test('swap `onclose` handler ', async () => {
|
|
15
|
-
const { endpoint } = await
|
|
14
|
+
const { endpoint, cleanup } = await createTestEdgeWsServer(8003);
|
|
15
|
+
onTestFinished(cleanup);
|
|
16
|
+
|
|
16
17
|
const ws = new WebSocket(endpoint);
|
|
17
18
|
const opened = new Trigger();
|
|
18
19
|
ws.onopen = () => {
|