@replit/river 0.5.2 → 0.6.1
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 +9 -0
- package/dist/__tests__/e2e.test.js +21 -9
- package/dist/__tests__/fixtures.d.ts +21 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -1
- package/dist/__tests__/fixtures.js +12 -0
- package/dist/__tests__/serialize.test.js +34 -1
- package/dist/codec/binary.d.ts +7 -0
- package/dist/codec/binary.d.ts.map +1 -0
- package/dist/codec/binary.js +20 -0
- package/dist/codec/codec.test.d.ts +4 -1
- package/dist/codec/codec.test.d.ts.map +1 -1
- package/dist/codec/codec.test.js +20 -8
- package/dist/codec/json.d.ts.map +1 -1
- package/dist/codec/json.js +39 -3
- package/dist/codec/types.d.ts +7 -7
- package/dist/codec/types.d.ts.map +1 -1
- package/dist/router/client.js +3 -3
- package/dist/testUtils.d.ts +2 -1
- package/dist/testUtils.d.ts.map +1 -1
- package/dist/testUtils.js +4 -3
- package/dist/transport/impls/stdio.d.ts.map +1 -1
- package/dist/transport/impls/stdio.js +8 -2
- package/dist/transport/impls/ws.d.ts +1 -0
- package/dist/transport/impls/ws.d.ts.map +1 -1
- package/dist/transport/impls/ws.js +5 -3
- package/dist/transport/types.d.ts +1 -1
- package/dist/transport/types.d.ts.map +1 -1
- package/dist/transport/types.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -5,4 +5,13 @@ It's like tRPC but...
|
|
|
5
5
|
- with JSON Schema Support
|
|
6
6
|
- with full-duplex streaming
|
|
7
7
|
- with support for service multiplexing
|
|
8
|
+
- with Result types and error handling
|
|
8
9
|
- over WebSockets
|
|
10
|
+
|
|
11
|
+
## Developing
|
|
12
|
+
|
|
13
|
+
- `npm i` -- install dependencies
|
|
14
|
+
- `npm check` -- lint
|
|
15
|
+
- `npm format` -- format
|
|
16
|
+
- `npm test` -- run tests
|
|
17
|
+
- `npm publish` -- cut a new release (should bump version in package.json first)
|
|
@@ -3,12 +3,14 @@ import { createWebSocketServer, createWsTransports, onServerReady, } from '../te
|
|
|
3
3
|
import { createServer } from '../router/server';
|
|
4
4
|
import { createClient } from '../router/client';
|
|
5
5
|
import http from 'http';
|
|
6
|
-
import { DIV_BY_ZERO, FallibleServiceConstructor, OrderingServiceConstructor, STREAM_ERROR, TestServiceConstructor, } from './fixtures';
|
|
6
|
+
import { BinaryFileServiceConstructor, DIV_BY_ZERO, FallibleServiceConstructor, OrderingServiceConstructor, STREAM_ERROR, TestServiceConstructor, } from './fixtures';
|
|
7
7
|
import { UNCAUGHT_ERROR } from '../router/result';
|
|
8
|
-
|
|
8
|
+
import { codecs } from '../codec/codec.test';
|
|
9
|
+
describe.each(codecs)('client <-> server integration test ($name codec)', async ({ codec }) => {
|
|
9
10
|
const server = http.createServer();
|
|
10
11
|
const port = await onServerReady(server);
|
|
11
12
|
const webSocketServer = await createWebSocketServer(server);
|
|
13
|
+
const getTransports = () => createWsTransports(port, webSocketServer, codec);
|
|
12
14
|
afterAll(() => {
|
|
13
15
|
webSocketServer.clients.forEach((socket) => {
|
|
14
16
|
socket.close();
|
|
@@ -16,7 +18,7 @@ describe('client <-> server integration test', async () => {
|
|
|
16
18
|
server.close();
|
|
17
19
|
});
|
|
18
20
|
test('rpc', async () => {
|
|
19
|
-
const [clientTransport, serverTransport] =
|
|
21
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
20
22
|
const serviceDefs = { test: TestServiceConstructor() };
|
|
21
23
|
const server = await createServer(serverTransport, serviceDefs);
|
|
22
24
|
const client = createClient(clientTransport);
|
|
@@ -25,7 +27,7 @@ describe('client <-> server integration test', async () => {
|
|
|
25
27
|
expect(result.payload).toStrictEqual({ result: 3 });
|
|
26
28
|
});
|
|
27
29
|
test('fallible rpc', async () => {
|
|
28
|
-
const [clientTransport, serverTransport] =
|
|
30
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
29
31
|
const serviceDefs = { test: FallibleServiceConstructor() };
|
|
30
32
|
const server = await createServer(serverTransport, serviceDefs);
|
|
31
33
|
const client = createClient(clientTransport);
|
|
@@ -42,8 +44,18 @@ describe('client <-> server integration test', async () => {
|
|
|
42
44
|
},
|
|
43
45
|
});
|
|
44
46
|
});
|
|
47
|
+
test('rpc with binary (uint8array)', async () => {
|
|
48
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
49
|
+
const serviceDefs = { test: BinaryFileServiceConstructor() };
|
|
50
|
+
const server = await createServer(serverTransport, serviceDefs);
|
|
51
|
+
const client = createClient(clientTransport);
|
|
52
|
+
const result = await client.test.getFile({ file: 'test.py' });
|
|
53
|
+
assert(result.ok);
|
|
54
|
+
assert(result.payload.contents instanceof Uint8Array);
|
|
55
|
+
expect(new TextDecoder().decode(result.payload.contents)).toStrictEqual('contents for file test.py');
|
|
56
|
+
});
|
|
45
57
|
test('stream', async () => {
|
|
46
|
-
const [clientTransport, serverTransport] =
|
|
58
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
47
59
|
const serviceDefs = { test: TestServiceConstructor() };
|
|
48
60
|
const server = await createServer(serverTransport, serviceDefs);
|
|
49
61
|
const client = createClient(clientTransport);
|
|
@@ -61,7 +73,7 @@ describe('client <-> server integration test', async () => {
|
|
|
61
73
|
close();
|
|
62
74
|
});
|
|
63
75
|
test('fallible stream', async () => {
|
|
64
|
-
const [clientTransport, serverTransport] =
|
|
76
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
65
77
|
const serviceDefs = { test: FallibleServiceConstructor() };
|
|
66
78
|
const server = await createServer(serverTransport, serviceDefs);
|
|
67
79
|
const client = createClient(clientTransport);
|
|
@@ -84,7 +96,7 @@ describe('client <-> server integration test', async () => {
|
|
|
84
96
|
close();
|
|
85
97
|
});
|
|
86
98
|
test('message order is preserved in the face of disconnects', async () => {
|
|
87
|
-
const [clientTransport, serverTransport] =
|
|
99
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
88
100
|
const serviceDefs = { test: OrderingServiceConstructor() };
|
|
89
101
|
const server = await createServer(serverTransport, serviceDefs);
|
|
90
102
|
const client = createClient(clientTransport);
|
|
@@ -107,7 +119,7 @@ describe('client <-> server integration test', async () => {
|
|
|
107
119
|
});
|
|
108
120
|
const CONCURRENCY = 10;
|
|
109
121
|
test('concurrent rpcs', async () => {
|
|
110
|
-
const [clientTransport, serverTransport] =
|
|
122
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
111
123
|
const serviceDefs = { test: OrderingServiceConstructor() };
|
|
112
124
|
const server = await createServer(serverTransport, serviceDefs);
|
|
113
125
|
const client = createClient(clientTransport);
|
|
@@ -122,7 +134,7 @@ describe('client <-> server integration test', async () => {
|
|
|
122
134
|
}
|
|
123
135
|
});
|
|
124
136
|
test('concurrent streams', async () => {
|
|
125
|
-
const [clientTransport, serverTransport] =
|
|
137
|
+
const [clientTransport, serverTransport] = getTransports();
|
|
126
138
|
const serviceDefs = { test: TestServiceConstructor() };
|
|
127
139
|
const server = await createServer(serverTransport, serviceDefs);
|
|
128
140
|
const client = createClient(clientTransport);
|
|
@@ -89,6 +89,27 @@ export declare const OrderingServiceConstructor: () => {
|
|
|
89
89
|
};
|
|
90
90
|
};
|
|
91
91
|
};
|
|
92
|
+
export declare const BinaryFileServiceConstructor: () => {
|
|
93
|
+
name: "bin";
|
|
94
|
+
state: {};
|
|
95
|
+
procedures: {
|
|
96
|
+
getFile: {
|
|
97
|
+
input: import("@sinclair/typebox").TObject<{
|
|
98
|
+
file: import("@sinclair/typebox").TString;
|
|
99
|
+
}>;
|
|
100
|
+
output: import("@sinclair/typebox").TObject<{
|
|
101
|
+
contents: import("@sinclair/typebox").TUint8Array;
|
|
102
|
+
}>;
|
|
103
|
+
errors: import("@sinclair/typebox").TNever;
|
|
104
|
+
handler: (context: import("../router").ServiceContextWithState<{}>, input: import("../transport/message").TransportMessage<{
|
|
105
|
+
file: string;
|
|
106
|
+
}>) => Promise<import("../transport/message").TransportMessage<import("../router/result").Result<{
|
|
107
|
+
contents: Uint8Array;
|
|
108
|
+
}, never>>>;
|
|
109
|
+
type: "rpc";
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
};
|
|
92
113
|
export declare const DIV_BY_ZERO = "DIV_BY_ZERO";
|
|
93
114
|
export declare const STREAM_ERROR = "STREAM_ERROR";
|
|
94
115
|
export declare const FallibleServiceConstructor: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../__tests__/fixtures.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW;;;EAGtB,CAAC;AACH,eAAO,MAAM,YAAY;;EAA2C,CAAC;AAErE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BpB,CAAC;AAEhB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBxB,CAAC;AAEhB,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAC3C,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiExB,CAAC"}
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../__tests__/fixtures.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,WAAW;;;EAGtB,CAAC;AACH,eAAO,MAAM,YAAY;;EAA2C,CAAC;AAErE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BpB,CAAC;AAEhB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBxB,CAAC;AAEhB,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;CAc1B,CAAC;AAEhB,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAC3C,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiExB,CAAC"}
|
|
@@ -62,6 +62,18 @@ export const OrderingServiceConstructor = () => ServiceBuilder.create('test')
|
|
|
62
62
|
},
|
|
63
63
|
})
|
|
64
64
|
.finalize();
|
|
65
|
+
export const BinaryFileServiceConstructor = () => ServiceBuilder.create('bin')
|
|
66
|
+
.defineProcedure('getFile', {
|
|
67
|
+
type: 'rpc',
|
|
68
|
+
input: Type.Object({ file: Type.String() }),
|
|
69
|
+
output: Type.Object({ contents: Type.Uint8Array() }),
|
|
70
|
+
errors: Type.Never(),
|
|
71
|
+
async handler(_ctx, msg) {
|
|
72
|
+
const bytes = new TextEncoder().encode(`contents for file ${msg.payload.file}`);
|
|
73
|
+
return reply(msg, Ok({ contents: bytes }));
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
.finalize();
|
|
65
77
|
export const DIV_BY_ZERO = 'DIV_BY_ZERO';
|
|
66
78
|
export const STREAM_ERROR = 'STREAM_ERROR';
|
|
67
79
|
export const FallibleServiceConstructor = () => ServiceBuilder.create('fallible')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect, describe, test } from 'vitest';
|
|
2
2
|
import { serializeService } from '../router/builder';
|
|
3
|
-
import { FallibleServiceConstructor, TestServiceConstructor } from './fixtures';
|
|
3
|
+
import { BinaryFileServiceConstructor, FallibleServiceConstructor, TestServiceConstructor, } from './fixtures';
|
|
4
4
|
describe('serialize service to jsonschema', () => {
|
|
5
5
|
test('serialize basic service', () => {
|
|
6
6
|
const service = TestServiceConstructor();
|
|
@@ -48,6 +48,39 @@ describe('serialize service to jsonschema', () => {
|
|
|
48
48
|
},
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
|
+
test('serialize service with binary', () => {
|
|
52
|
+
const service = BinaryFileServiceConstructor();
|
|
53
|
+
expect(serializeService(service)).toStrictEqual({
|
|
54
|
+
name: 'bin',
|
|
55
|
+
procedures: {
|
|
56
|
+
getFile: {
|
|
57
|
+
errors: {
|
|
58
|
+
not: {},
|
|
59
|
+
},
|
|
60
|
+
input: {
|
|
61
|
+
properties: {
|
|
62
|
+
file: {
|
|
63
|
+
type: 'string',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: ['file'],
|
|
67
|
+
type: 'object',
|
|
68
|
+
},
|
|
69
|
+
output: {
|
|
70
|
+
properties: {
|
|
71
|
+
contents: {
|
|
72
|
+
type: 'Uint8Array',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
required: ['contents'],
|
|
76
|
+
type: 'object',
|
|
77
|
+
},
|
|
78
|
+
type: 'rpc',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
state: {},
|
|
82
|
+
});
|
|
83
|
+
});
|
|
51
84
|
test('serialize service with errors', () => {
|
|
52
85
|
const service = FallibleServiceConstructor();
|
|
53
86
|
expect(serializeService(service)).toStrictEqual({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../codec/binary.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,KAczB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { decode, encode } from '@msgpack/msgpack';
|
|
2
|
+
/**
|
|
3
|
+
* Binary codec, uses [msgpack](https://www.npmjs.com/package/@msgpack/msgpack) under the hood
|
|
4
|
+
* @type {Codec}
|
|
5
|
+
*/
|
|
6
|
+
export const BinaryCodec = {
|
|
7
|
+
toBuffer: encode,
|
|
8
|
+
fromBuffer: (buff) => {
|
|
9
|
+
try {
|
|
10
|
+
const res = decode(buff);
|
|
11
|
+
if (typeof res !== 'object') {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return res;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.test.d.ts","sourceRoot":"","sources":["../../codec/codec.test.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"codec.test.d.ts","sourceRoot":"","sources":["../../codec/codec.test.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,MAAM;;;GAGlB,CAAC"}
|
package/dist/codec/codec.test.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import { BinaryCodec } from './binary';
|
|
1
2
|
import { NaiveJsonCodec } from './json';
|
|
2
3
|
import { describe, test, expect } from 'vitest';
|
|
3
|
-
|
|
4
|
+
export const codecs = [
|
|
5
|
+
{ name: 'naive', codec: NaiveJsonCodec },
|
|
6
|
+
{ name: 'binary', codec: BinaryCodec },
|
|
7
|
+
];
|
|
8
|
+
describe.each(codecs)('codec -- $name', ({ codec }) => {
|
|
4
9
|
test('empty object', () => {
|
|
5
10
|
const msg = {};
|
|
6
|
-
expect(
|
|
11
|
+
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
|
|
7
12
|
});
|
|
8
13
|
test('simple test', () => {
|
|
9
14
|
const msg = { abc: 123, def: 'cool' };
|
|
10
|
-
expect(
|
|
15
|
+
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
|
|
11
16
|
});
|
|
12
17
|
test('deeply nested test', () => {
|
|
13
18
|
const msg = {
|
|
@@ -18,12 +23,19 @@ describe('naive json codec', () => {
|
|
|
18
23
|
},
|
|
19
24
|
},
|
|
20
25
|
};
|
|
21
|
-
expect(
|
|
26
|
+
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
|
|
27
|
+
});
|
|
28
|
+
test('buffer test', () => {
|
|
29
|
+
const msg = {
|
|
30
|
+
buff: Uint8Array.from([0, 42, 100, 255]),
|
|
31
|
+
};
|
|
32
|
+
expect(codec.fromBuffer(codec.toBuffer(msg))).toStrictEqual(msg);
|
|
22
33
|
});
|
|
23
34
|
test('invalid json returns null', () => {
|
|
24
|
-
|
|
25
|
-
expect(
|
|
26
|
-
expect(
|
|
27
|
-
expect(
|
|
35
|
+
const encoder = new TextEncoder();
|
|
36
|
+
expect(codec.fromBuffer(encoder.encode(''))).toBeNull();
|
|
37
|
+
expect(codec.fromBuffer(encoder.encode('['))).toBeNull();
|
|
38
|
+
expect(codec.fromBuffer(encoder.encode('[{}'))).toBeNull();
|
|
39
|
+
expect(codec.fromBuffer(encoder.encode('{"a":1}[]'))).toBeNull();
|
|
28
40
|
});
|
|
29
41
|
});
|
package/dist/codec/json.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../codec/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../codec/json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAwBhC;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,KA0B5B,CAAC"}
|
package/dist/codec/json.js
CHANGED
|
@@ -1,12 +1,48 @@
|
|
|
1
|
+
const encoder = new TextEncoder();
|
|
2
|
+
const decoder = new TextDecoder();
|
|
3
|
+
// Convert Uint8Array to base64
|
|
4
|
+
function uint8ArrayToBase64(uint8Array) {
|
|
5
|
+
let binary = '';
|
|
6
|
+
uint8Array.forEach((byte) => {
|
|
7
|
+
binary += String.fromCharCode(byte);
|
|
8
|
+
});
|
|
9
|
+
return btoa(binary);
|
|
10
|
+
}
|
|
11
|
+
// Convert base64 to Uint8Array
|
|
12
|
+
function base64ToUint8Array(base64) {
|
|
13
|
+
const binaryString = atob(base64);
|
|
14
|
+
const uint8Array = new Uint8Array(binaryString.length);
|
|
15
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
16
|
+
uint8Array[i] = binaryString.charCodeAt(i);
|
|
17
|
+
}
|
|
18
|
+
return uint8Array;
|
|
19
|
+
}
|
|
1
20
|
/**
|
|
2
21
|
* Naive JSON codec implementation using JSON.stringify and JSON.parse.
|
|
3
22
|
* @type {Codec}
|
|
4
23
|
*/
|
|
5
24
|
export const NaiveJsonCodec = {
|
|
6
|
-
|
|
7
|
-
|
|
25
|
+
toBuffer: (obj) => {
|
|
26
|
+
return encoder.encode(JSON.stringify(obj, function replacer(key) {
|
|
27
|
+
let val = this[key];
|
|
28
|
+
if (val instanceof Uint8Array) {
|
|
29
|
+
return { $t: uint8ArrayToBase64(val) };
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return val;
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
},
|
|
36
|
+
fromBuffer: (buff) => {
|
|
8
37
|
try {
|
|
9
|
-
return JSON.parse(
|
|
38
|
+
return JSON.parse(decoder.decode(buff), function reviver(_key, val) {
|
|
39
|
+
if (val?.$t) {
|
|
40
|
+
return base64ToUint8Array(val.$t);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return val;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
10
46
|
}
|
|
11
47
|
catch {
|
|
12
48
|
return null;
|
package/dist/codec/types.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Codec interface for encoding and decoding objects to and from
|
|
2
|
+
* Codec interface for encoding and decoding objects to and from Uint8 buffers.
|
|
3
3
|
* Used to prepare messages for use by the transport layer.
|
|
4
4
|
*/
|
|
5
5
|
export interface Codec {
|
|
6
6
|
/**
|
|
7
|
-
* Encodes an object to a
|
|
7
|
+
* Encodes an object to a Uint8 buffer.
|
|
8
8
|
* @param obj - The object to encode.
|
|
9
|
-
* @returns The encoded
|
|
9
|
+
* @returns The encoded Uint8 buffer.
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
toBuffer(obj: object): Uint8Array;
|
|
12
12
|
/**
|
|
13
|
-
* Decodes an object from a
|
|
14
|
-
* @param buf - The
|
|
13
|
+
* Decodes an object from a Uint8 buffer.
|
|
14
|
+
* @param buf - The Uint8 buffer to decode.
|
|
15
15
|
* @returns The decoded object, or null if decoding failed.
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
fromBuffer(buf: Uint8Array): object | null;
|
|
18
18
|
}
|
|
19
19
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../codec/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB;;;;OAIG;IACH,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../codec/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB;;;;OAIG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC;IAClC;;;;OAIG;IACH,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;CAC5C"}
|
package/dist/router/client.js
CHANGED
|
@@ -39,9 +39,9 @@ export const createClient = (transport) => _createRecursiveProxy(async (opts) =>
|
|
|
39
39
|
const [input] = opts.args;
|
|
40
40
|
const streamId = nanoid();
|
|
41
41
|
function belongsToSameStream(msg) {
|
|
42
|
-
return (msg.
|
|
43
|
-
msg.
|
|
44
|
-
msg.
|
|
42
|
+
return (msg.serviceName === serviceName &&
|
|
43
|
+
msg.procedureName === procName &&
|
|
44
|
+
(msg.streamId === streamId || msg.streamId === 'global'));
|
|
45
45
|
}
|
|
46
46
|
if (input === undefined) {
|
|
47
47
|
// stream case (stream methods are called with zero arguments)
|
package/dist/testUtils.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { Procedure, ServiceContext } from './router';
|
|
|
8
8
|
import { OpaqueTransportMessage, TransportMessage } from './transport';
|
|
9
9
|
import { Pushable } from 'it-pushable';
|
|
10
10
|
import { Result, RiverError, RiverUncaughtSchema } from './router/result';
|
|
11
|
+
import { Codec } from './codec';
|
|
11
12
|
/**
|
|
12
13
|
* Creates a WebSocket server instance using the provided HTTP server.
|
|
13
14
|
* Only used as helper for testing.
|
|
@@ -36,7 +37,7 @@ export declare function createLocalWebSocketClient(port: number): Promise<WebSoc
|
|
|
36
37
|
* @param wss - The WebSocketServer instance to use for the server transport.
|
|
37
38
|
* @returns An array containing the client and server {@link WebSocketTransport} instances.
|
|
38
39
|
*/
|
|
39
|
-
export declare function createWsTransports(port: number, wss: WebSocketServer): [WebSocketTransport, WebSocketTransport];
|
|
40
|
+
export declare function createWsTransports(port: number, wss: WebSocketServer, codec?: Codec): [WebSocketTransport, WebSocketTransport];
|
|
40
41
|
/**
|
|
41
42
|
* Transforms an RPC procedure definition into a normal function call.
|
|
42
43
|
* This should only be used for testing.
|
package/dist/testUtils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../testUtils.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AACrC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAY,MAAM,aAAa,CAAC;AACjD,OAAO,EAEL,MAAM,EACN,UAAU,EACV,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../testUtils.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AACrC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAY,MAAM,aAAa,CAAC;AACjD,OAAO,EAEL,MAAM,EACN,UAAU,EACV,mBAAmB,EAEpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,4EAE9D;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAWxE;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,sBAE5D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,KAAK,CAAC,EAAE,KAAK,GACZ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAuB1C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACzB,KAAK,SAAS,MAAM,GAAG,OAAO,EAC9B,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,UAAU,EAEpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACtC,eAAe,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,SAGxC,OAAO,CAAC,CAAC,KACb,QACD,OAAO,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,0BAA0B,CAAC,CAAC,CAClE,CAYF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,KAAK,SAAS,MAAM,GAAG,OAAO,EAC9B,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,UAAU,EAEpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACzC,eAAe,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GAC9C;IACD,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC;CAC5E,CAuDA;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,SAAS,MAAM,EAC9D,OAAO,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,6BAUlB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,sBAAsB,CAKpE"}
|
package/dist/testUtils.js
CHANGED
|
@@ -48,11 +48,12 @@ export async function createLocalWebSocketClient(port) {
|
|
|
48
48
|
* @param wss - The WebSocketServer instance to use for the server transport.
|
|
49
49
|
* @returns An array containing the client and server {@link WebSocketTransport} instances.
|
|
50
50
|
*/
|
|
51
|
-
export function createWsTransports(port, wss) {
|
|
51
|
+
export function createWsTransports(port, wss, codec) {
|
|
52
|
+
const options = codec ? { codec } : undefined;
|
|
52
53
|
return [
|
|
53
54
|
new WebSocketTransport(async () => {
|
|
54
55
|
return createLocalWebSocketClient(port);
|
|
55
|
-
}, 'client'),
|
|
56
|
+
}, 'client', options),
|
|
56
57
|
new WebSocketTransport(async () => {
|
|
57
58
|
return new Promise((resolve) => {
|
|
58
59
|
wss.on('connection', async function onConnect(serverSock) {
|
|
@@ -60,7 +61,7 @@ export function createWsTransports(port, wss) {
|
|
|
60
61
|
resolve(serverSock);
|
|
61
62
|
});
|
|
62
63
|
});
|
|
63
|
-
}, 'SERVER'),
|
|
64
|
+
}, 'SERVER', options),
|
|
64
65
|
];
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../transport/impls/stdio.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,UAAU,OAAO;IACf,KAAK,EAAE,KAAK,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../transport/impls/stdio.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,UAAU,OAAO;IACf,KAAK,EAAE,KAAK,CAAC;CACd;AAQD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC;IAC7B;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAE9B;;;;;OAKG;gBAED,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,GAAE,MAAM,CAAC,cAA8B,EAC5C,MAAM,GAAE,MAAM,CAAC,cAA+B,EAC9C,eAAe,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAcpC;;;;OAIG;IACH,IAAI,CAAC,GAAG,EAAE,sBAAsB,GAAG,MAAM;IAWzC;;OAEG;IACG,KAAK;CACZ"}
|
|
@@ -4,6 +4,7 @@ import readline from 'readline';
|
|
|
4
4
|
const defaultOptions = {
|
|
5
5
|
codec: NaiveJsonCodec,
|
|
6
6
|
};
|
|
7
|
+
const newlineBuff = new TextEncoder().encode('\n');
|
|
7
8
|
/**
|
|
8
9
|
* A transport implementation that uses standard input and output streams.
|
|
9
10
|
* @extends Transport
|
|
@@ -31,7 +32,8 @@ export class StdioTransport extends Transport {
|
|
|
31
32
|
const rl = readline.createInterface({
|
|
32
33
|
input: this.input,
|
|
33
34
|
});
|
|
34
|
-
|
|
35
|
+
const encoder = new TextEncoder();
|
|
36
|
+
rl.on('line', (msg) => this.onMessage(encoder.encode(msg)));
|
|
35
37
|
}
|
|
36
38
|
/**
|
|
37
39
|
* Sends a message over the transport.
|
|
@@ -40,7 +42,11 @@ export class StdioTransport extends Transport {
|
|
|
40
42
|
*/
|
|
41
43
|
send(msg) {
|
|
42
44
|
const id = msg.id;
|
|
43
|
-
this.
|
|
45
|
+
const payload = this.codec.toBuffer(msg);
|
|
46
|
+
const out = new Uint8Array(payload.length + newlineBuff.length);
|
|
47
|
+
out.set(payload, 0);
|
|
48
|
+
out.set(newlineBuff, payload.length);
|
|
49
|
+
this.output.write(out);
|
|
44
50
|
return id;
|
|
45
51
|
}
|
|
46
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../../transport/impls/ws.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,UAAU,OAAO;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../../transport/impls/ws.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,UAAU,OAAO;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,aAAa,GAAG,MAAM,CAAC;CACpC;AAQD,KAAK,eAAe,GAAG;IAAE,EAAE,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;IAC/C;;OAEG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IAEjB;;;OAGG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAE5C;;;OAGG;IACH,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAE5B;;;;;OAKG;gBAED,QAAQ,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,EAClC,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAWpC;;OAEG;YACW,UAAU;IAmExB;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,sBAAsB,GAAG,SAAS;IAyB5C;;OAEG;IACG,KAAK;CAKZ"}
|
|
@@ -4,6 +4,7 @@ import { log } from '../../logging';
|
|
|
4
4
|
const defaultOptions = {
|
|
5
5
|
retryIntervalMs: 250,
|
|
6
6
|
codec: NaiveJsonCodec,
|
|
7
|
+
binaryType: 'arraybuffer',
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
10
|
* A transport implementation that uses a WebSocket connection with automatic reconnection.
|
|
@@ -79,7 +80,8 @@ export class WebSocketTransport extends Transport {
|
|
|
79
80
|
if ('ws' in res && res.ws.readyState === res.ws.OPEN) {
|
|
80
81
|
log?.info(`${this.clientId} -- websocket ok`);
|
|
81
82
|
this.ws = res.ws;
|
|
82
|
-
this.ws.
|
|
83
|
+
this.ws.binaryType = 'arraybuffer';
|
|
84
|
+
this.ws.onmessage = (msg) => this.onMessage(msg.data);
|
|
83
85
|
this.ws.onclose = () => {
|
|
84
86
|
this.reconnectPromise = undefined;
|
|
85
87
|
this.tryConnect().catch();
|
|
@@ -93,7 +95,7 @@ export class WebSocketTransport extends Transport {
|
|
|
93
95
|
throw new Error(err);
|
|
94
96
|
}
|
|
95
97
|
log?.info(`${this.clientId} -- sending ${JSON.stringify(msg)}`);
|
|
96
|
-
this.ws.send(this.codec.
|
|
98
|
+
this.ws.send(this.codec.toBuffer(msg));
|
|
97
99
|
}
|
|
98
100
|
this.sendQueue = [];
|
|
99
101
|
return;
|
|
@@ -119,7 +121,7 @@ export class WebSocketTransport extends Transport {
|
|
|
119
121
|
this.sendBuffer.set(id, msg);
|
|
120
122
|
if (this.ws && this.ws.readyState === this.ws.OPEN) {
|
|
121
123
|
log?.info(`${this.clientId} -- sending ${JSON.stringify(msg)}`);
|
|
122
|
-
this.ws.send(this.codec.
|
|
124
|
+
this.ws.send(this.codec.toBuffer(msg));
|
|
123
125
|
}
|
|
124
126
|
else {
|
|
125
127
|
log?.info(`${this.clientId} -- transport not ready, queuing ${JSON.stringify(msg)}`);
|
|
@@ -33,7 +33,7 @@ export declare abstract class Transport {
|
|
|
33
33
|
* You generally shouldn't need to override this in downstream transport implementations.
|
|
34
34
|
* @param msg The received message.
|
|
35
35
|
*/
|
|
36
|
-
onMessage(msg:
|
|
36
|
+
onMessage(msg: Uint8Array): void;
|
|
37
37
|
/**
|
|
38
38
|
* Adds a message listener to this transport.
|
|
39
39
|
* @param handler The message handler to add.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../transport/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EAEL,SAAS,EACT,sBAAsB,EAGtB,iBAAiB,EAGlB,MAAM,WAAW,CAAC;AAGnB;;;;GAIG;AACH,8BAAsB,SAAS;IAC7B;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,sBAAsB,KAAK,IAAI,CAAC,CAAC;IAGrD;;OAEG;IACH,UAAU,EAAE,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAEnD;;;;OAIG;gBACS,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB;IAOrD;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../transport/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EAEL,SAAS,EACT,sBAAsB,EAGtB,iBAAiB,EAGlB,MAAM,WAAW,CAAC;AAGnB;;;;GAIG;AACH,8BAAsB,SAAS;IAC7B;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;IAEb;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,sBAAsB,KAAK,IAAI,CAAC,CAAC;IAGrD;;OAEG;IACH,UAAU,EAAE,GAAG,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IAEnD;;;;OAIG;gBACS,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB;IAOrD;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,UAAU;IAuCzB;;;OAGG;IACH,kBAAkB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,sBAAsB,KAAK,IAAI,GAAG,IAAI;IAIxE;;;OAGG;IACH,qBAAqB,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,sBAAsB,KAAK,IAAI,GAAG,IAAI;IAI3E,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,GAAG,SAAS;IACrD,QAAQ,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAChC"}
|
package/dist/transport/types.js
CHANGED
|
@@ -41,7 +41,7 @@ export class Transport {
|
|
|
41
41
|
* @param msg The received message.
|
|
42
42
|
*/
|
|
43
43
|
onMessage(msg) {
|
|
44
|
-
const parsedMsg = this.codec.
|
|
44
|
+
const parsedMsg = this.codec.fromBuffer(msg);
|
|
45
45
|
if (parsedMsg === null) {
|
|
46
46
|
log?.warn(`${this.clientId} -- received malformed msg: ${msg}`);
|
|
47
47
|
return;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@replit/river",
|
|
3
3
|
"sideEffects": false,
|
|
4
4
|
"description": "It's like tRPC but... with JSON Schema Support, duplex streaming and support for service multiplexing. Transport agnostic!",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.6.1",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./dist/router/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@msgpack/msgpack": "^3.0.0-beta2",
|
|
20
21
|
"@sinclair/typebox": "^0.31.8",
|
|
21
22
|
"isomorphic-ws": "^5.0.0",
|
|
22
23
|
"it-pushable": "^3.2.1",
|