@replit/river 0.9.3 → 0.10.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.
Files changed (129) hide show
  1. package/dist/{router/builder.d.ts → builder-3c4485f0.d.ts} +82 -28
  2. package/dist/chunk-7WJ6YLE5.js +683 -0
  3. package/dist/chunk-AJQU4AZG.js +284 -0
  4. package/dist/chunk-ORAG7IAU.js +0 -0
  5. package/dist/chunk-PC65ZFWJ.js +29 -0
  6. package/dist/chunk-R6H2BIMC.js +49 -0
  7. package/dist/chunk-RGMHF6PF.js +65 -0
  8. package/dist/chunk-SLUSVGQH.js +30 -0
  9. package/dist/chunk-UU2Z7LDR.js +113 -0
  10. package/dist/chunk-WVT5QXMZ.js +20 -0
  11. package/dist/chunk-ZE4MX7DF.js +75 -0
  12. package/dist/codec/index.cjs +94 -0
  13. package/dist/codec/index.d.cts +15 -0
  14. package/dist/codec/index.d.ts +15 -4
  15. package/dist/codec/index.js +10 -2
  16. package/dist/connection-8e19874c.d.ts +11 -0
  17. package/dist/connection-f7688cc1.d.ts +11 -0
  18. package/dist/logging/index.cjs +56 -0
  19. package/dist/logging/index.d.cts +28 -0
  20. package/dist/logging/index.d.ts +6 -6
  21. package/dist/logging/index.js +9 -40
  22. package/dist/router/index.cjs +770 -0
  23. package/dist/router/index.d.cts +114 -0
  24. package/dist/router/index.d.ts +114 -10
  25. package/dist/router/index.js +24 -4
  26. package/dist/transport/impls/ws/client.cjs +505 -0
  27. package/dist/transport/impls/ws/client.d.cts +42 -0
  28. package/dist/transport/impls/ws/client.d.ts +9 -12
  29. package/dist/transport/impls/ws/client.js +10 -101
  30. package/dist/transport/impls/ws/server.cjs +457 -0
  31. package/dist/transport/impls/ws/server.d.cts +21 -0
  32. package/dist/transport/impls/ws/server.d.ts +14 -10
  33. package/dist/transport/impls/ws/server.js +11 -47
  34. package/dist/transport/index.cjs +362 -0
  35. package/dist/transport/{transport.d.ts → index.d.cts} +119 -7
  36. package/dist/transport/index.d.ts +273 -13
  37. package/dist/transport/index.js +20 -23
  38. package/dist/{codec/types.d.ts → types-3e5768ec.d.ts} +3 -2
  39. package/dist/util/testHelpers.cjs +731 -0
  40. package/dist/util/testHelpers.d.cts +79 -0
  41. package/dist/util/testHelpers.d.ts +34 -108
  42. package/dist/util/testHelpers.js +137 -320
  43. package/package.json +52 -23
  44. package/dist/__tests__/bandwidth.bench.d.ts +0 -2
  45. package/dist/__tests__/bandwidth.bench.d.ts.map +0 -1
  46. package/dist/__tests__/bandwidth.bench.js +0 -90
  47. package/dist/__tests__/e2e.test.d.ts +0 -2
  48. package/dist/__tests__/e2e.test.d.ts.map +0 -1
  49. package/dist/__tests__/e2e.test.js +0 -316
  50. package/dist/__tests__/fixtures/cleanup.d.ts +0 -12
  51. package/dist/__tests__/fixtures/cleanup.d.ts.map +0 -1
  52. package/dist/__tests__/fixtures/cleanup.js +0 -39
  53. package/dist/__tests__/fixtures/largePayload.json +0 -33
  54. package/dist/__tests__/fixtures/observable.d.ts +0 -26
  55. package/dist/__tests__/fixtures/observable.d.ts.map +0 -1
  56. package/dist/__tests__/fixtures/observable.js +0 -38
  57. package/dist/__tests__/fixtures/observable.test.d.ts +0 -2
  58. package/dist/__tests__/fixtures/observable.test.d.ts.map +0 -1
  59. package/dist/__tests__/fixtures/observable.test.js +0 -39
  60. package/dist/__tests__/fixtures/services.d.ts +0 -288
  61. package/dist/__tests__/fixtures/services.d.ts.map +0 -1
  62. package/dist/__tests__/fixtures/services.js +0 -224
  63. package/dist/__tests__/handler.test.d.ts +0 -2
  64. package/dist/__tests__/handler.test.d.ts.map +0 -1
  65. package/dist/__tests__/handler.test.js +0 -121
  66. package/dist/__tests__/invariants.test.d.ts +0 -2
  67. package/dist/__tests__/invariants.test.d.ts.map +0 -1
  68. package/dist/__tests__/invariants.test.js +0 -138
  69. package/dist/__tests__/serialize.test.d.ts +0 -2
  70. package/dist/__tests__/serialize.test.d.ts.map +0 -1
  71. package/dist/__tests__/serialize.test.js +0 -208
  72. package/dist/__tests__/typescript-stress.test.d.ts +0 -1583
  73. package/dist/__tests__/typescript-stress.test.d.ts.map +0 -1
  74. package/dist/__tests__/typescript-stress.test.js +0 -123
  75. package/dist/codec/binary.d.ts +0 -7
  76. package/dist/codec/binary.d.ts.map +0 -1
  77. package/dist/codec/binary.js +0 -20
  78. package/dist/codec/codec.test.d.ts +0 -5
  79. package/dist/codec/codec.test.d.ts.map +0 -1
  80. package/dist/codec/codec.test.js +0 -41
  81. package/dist/codec/index.d.ts.map +0 -1
  82. package/dist/codec/json.d.ts +0 -7
  83. package/dist/codec/json.d.ts.map +0 -1
  84. package/dist/codec/json.js +0 -51
  85. package/dist/codec/types.d.ts.map +0 -1
  86. package/dist/codec/types.js +0 -1
  87. package/dist/logging/index.d.ts.map +0 -1
  88. package/dist/router/builder.d.ts.map +0 -1
  89. package/dist/router/builder.js +0 -91
  90. package/dist/router/client.d.ts +0 -68
  91. package/dist/router/client.d.ts.map +0 -1
  92. package/dist/router/client.js +0 -159
  93. package/dist/router/context.d.ts +0 -30
  94. package/dist/router/context.d.ts.map +0 -1
  95. package/dist/router/context.js +0 -1
  96. package/dist/router/index.d.ts.map +0 -1
  97. package/dist/router/result.d.ts +0 -25
  98. package/dist/router/result.d.ts.map +0 -1
  99. package/dist/router/result.js +0 -18
  100. package/dist/router/server.d.ts +0 -39
  101. package/dist/router/server.d.ts.map +0 -1
  102. package/dist/router/server.js +0 -217
  103. package/dist/transport/events.d.ts +0 -19
  104. package/dist/transport/events.d.ts.map +0 -1
  105. package/dist/transport/events.js +0 -26
  106. package/dist/transport/impls/stdio/stdio.d.ts +0 -33
  107. package/dist/transport/impls/stdio/stdio.d.ts.map +0 -1
  108. package/dist/transport/impls/stdio/stdio.js +0 -75
  109. package/dist/transport/impls/stdio/stdio.test.d.ts +0 -2
  110. package/dist/transport/impls/stdio/stdio.test.d.ts.map +0 -1
  111. package/dist/transport/impls/stdio/stdio.test.js +0 -25
  112. package/dist/transport/impls/ws/client.d.ts.map +0 -1
  113. package/dist/transport/impls/ws/connection.d.ts +0 -11
  114. package/dist/transport/impls/ws/connection.d.ts.map +0 -1
  115. package/dist/transport/impls/ws/connection.js +0 -23
  116. package/dist/transport/impls/ws/server.d.ts.map +0 -1
  117. package/dist/transport/impls/ws/ws.test.d.ts +0 -2
  118. package/dist/transport/impls/ws/ws.test.d.ts.map +0 -1
  119. package/dist/transport/impls/ws/ws.test.js +0 -117
  120. package/dist/transport/index.d.ts.map +0 -1
  121. package/dist/transport/message.d.ts +0 -143
  122. package/dist/transport/message.d.ts.map +0 -1
  123. package/dist/transport/message.js +0 -113
  124. package/dist/transport/message.test.d.ts +0 -2
  125. package/dist/transport/message.test.d.ts.map +0 -1
  126. package/dist/transport/message.test.js +0 -52
  127. package/dist/transport/transport.d.ts.map +0 -1
  128. package/dist/transport/transport.js +0 -281
  129. package/dist/util/testHelpers.d.ts.map +0 -1
@@ -1,90 +0,0 @@
1
- import http from 'http';
2
- import { assert, bench, describe } from 'vitest';
3
- import { createWebSocketServer, createWsTransports, onServerReady, } from '../util/testHelpers';
4
- import largePayload from './fixtures/largePayload.json';
5
- import { TestServiceConstructor } from './fixtures/services';
6
- import { createServer } from '../router/server';
7
- import { createClient } from '../router/client';
8
- import { StupidlyLargeService } from './typescript-stress.test';
9
- import { waitForMessage } from '../transport';
10
- let smallId = 0;
11
- let largeId = 0;
12
- const dummyPayloadSmall = () => ({
13
- id: `${smallId++}`,
14
- from: 'client',
15
- to: 'SERVER',
16
- serviceName: 'test',
17
- procedureName: 'test',
18
- streamId: 'test',
19
- controlFlags: 0,
20
- payload: {
21
- msg: 'cool',
22
- },
23
- });
24
- const dummyPayloadLarge = () => ({
25
- id: `${largeId++}`,
26
- from: 'client',
27
- to: 'SERVER',
28
- serviceName: 'test',
29
- procedureName: 'test',
30
- streamId: 'test',
31
- controlFlags: 0,
32
- payload: largePayload,
33
- });
34
- const BENCH_DURATION = 1000;
35
- describe('transport level bandwidth', async () => {
36
- const server = http.createServer();
37
- const port = await onServerReady(server);
38
- const webSocketServer = await createWebSocketServer(server);
39
- const [clientTransport, serverTransport] = createWsTransports(port, webSocketServer);
40
- bench('send and recv (small payload)', async () => {
41
- const id = clientTransport.send(dummyPayloadSmall());
42
- await waitForMessage(serverTransport, (msg) => msg.id === id);
43
- return;
44
- }, { time: BENCH_DURATION });
45
- bench('send and recv (large payload)', async () => {
46
- const id = clientTransport.send(dummyPayloadLarge());
47
- await waitForMessage(serverTransport, (msg) => msg.id === id);
48
- return;
49
- }, { time: BENCH_DURATION });
50
- });
51
- describe('simple router level bandwidth', async () => {
52
- const httpServer = http.createServer();
53
- const port = await onServerReady(httpServer);
54
- const webSocketServer = await createWebSocketServer(httpServer);
55
- const [clientTransport, serverTransport] = createWsTransports(port, webSocketServer);
56
- const serviceDefs = { test: TestServiceConstructor() };
57
- const server = await createServer(serverTransport, serviceDefs);
58
- const client = createClient(clientTransport);
59
- bench('rpc (wait for response)', async () => {
60
- const result = await client.test.add.rpc({ n: 1 });
61
- assert(result.ok);
62
- }, { time: BENCH_DURATION });
63
- const [input, output] = await client.test.echo.stream();
64
- bench('stream (wait for response)', async () => {
65
- input.push({ msg: 'abc', ignore: false });
66
- const result = await output.next();
67
- assert(result.value && result.value.ok);
68
- }, { time: BENCH_DURATION });
69
- bench('stream', async () => {
70
- input.push({ msg: 'abc', ignore: false });
71
- }, { time: BENCH_DURATION });
72
- });
73
- describe('complex (50 procedures) router level bandwidth', async () => {
74
- const httpServer = http.createServer();
75
- const port = await onServerReady(httpServer);
76
- const webSocketServer = await createWebSocketServer(httpServer);
77
- const [clientTransport, serverTransport] = createWsTransports(port, webSocketServer);
78
- const serviceDefs = {
79
- a: StupidlyLargeService(),
80
- b: StupidlyLargeService(),
81
- c: StupidlyLargeService(),
82
- d: StupidlyLargeService(),
83
- };
84
- const server = await createServer(serverTransport, serviceDefs);
85
- const client = createClient(clientTransport);
86
- bench('rpc (wait for response)', async () => {
87
- const result = await client.b.f35.rpc({ a: 1 });
88
- assert(result.ok);
89
- }, { time: BENCH_DURATION });
90
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=e2e.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"e2e.test.d.ts","sourceRoot":"","sources":["../../__tests__/e2e.test.ts"],"names":[],"mappings":""}
@@ -1,316 +0,0 @@
1
- import { afterAll, assert, describe, expect, test } from 'vitest';
2
- import { createLocalWebSocketClient, createWebSocketServer, createWsTransports, iterNext, onServerReady, } from '../util/testHelpers';
3
- import { createServer } from '../router/server';
4
- import { createClient } from '../router/client';
5
- import http from 'http';
6
- import { BinaryFileServiceConstructor, DIV_BY_ZERO, FallibleServiceConstructor, OrderingServiceConstructor, STREAM_ERROR, SubscribableServiceConstructor, UploadableServiceConstructor, TestServiceConstructor, } from './fixtures/services';
7
- import { UNCAUGHT_ERROR } from '../router/result';
8
- import { codecs } from '../codec/codec.test';
9
- import { WebSocketClientTransport } from '../transport/impls/ws/client';
10
- import { WebSocketServerTransport } from '../transport/impls/ws/server';
11
- import { testFinishesCleanly } from './fixtures/cleanup';
12
- describe.each(codecs)('client <-> server integration test ($name codec)', async ({ codec }) => {
13
- const httpServer = http.createServer();
14
- const port = await onServerReady(httpServer);
15
- const webSocketServer = await createWebSocketServer(httpServer);
16
- const getTransports = () => createWsTransports(port, webSocketServer, codec);
17
- afterAll(() => {
18
- webSocketServer.close();
19
- httpServer.close();
20
- });
21
- test('rpc', async () => {
22
- const [clientTransport, serverTransport] = getTransports();
23
- const serviceDefs = { test: TestServiceConstructor() };
24
- const server = await createServer(serverTransport, serviceDefs);
25
- const client = createClient(clientTransport);
26
- const result = await client.test.add.rpc({ n: 3 });
27
- assert(result.ok);
28
- expect(result.payload).toStrictEqual({ result: 3 });
29
- await testFinishesCleanly({
30
- clientTransports: [clientTransport],
31
- serverTransport,
32
- server,
33
- });
34
- });
35
- test('fallible rpc', async () => {
36
- const [clientTransport, serverTransport] = getTransports();
37
- const serviceDefs = { test: FallibleServiceConstructor() };
38
- const server = await createServer(serverTransport, serviceDefs);
39
- const client = createClient(clientTransport);
40
- const result = await client.test.divide.rpc({ a: 10, b: 2 });
41
- assert(result.ok);
42
- expect(result.payload).toStrictEqual({ result: 5 });
43
- const result2 = await client.test.divide.rpc({ a: 10, b: 0 });
44
- assert(!result2.ok);
45
- expect(result2.payload).toStrictEqual({
46
- code: DIV_BY_ZERO,
47
- message: 'Cannot divide by zero',
48
- extras: {
49
- test: 'abc',
50
- },
51
- });
52
- await testFinishesCleanly({
53
- clientTransports: [clientTransport],
54
- serverTransport,
55
- server,
56
- });
57
- });
58
- test('rpc with binary (uint8array)', async () => {
59
- const [clientTransport, serverTransport] = getTransports();
60
- const serviceDefs = { test: BinaryFileServiceConstructor() };
61
- const server = await createServer(serverTransport, serviceDefs);
62
- const client = createClient(clientTransport);
63
- const result = await client.test.getFile.rpc({ file: 'test.py' });
64
- assert(result.ok);
65
- assert(result.payload.contents instanceof Uint8Array);
66
- expect(new TextDecoder().decode(result.payload.contents)).toStrictEqual('contents for file test.py');
67
- await testFinishesCleanly({
68
- clientTransports: [clientTransport],
69
- serverTransport,
70
- server,
71
- });
72
- });
73
- test('stream', async () => {
74
- const [clientTransport, serverTransport] = getTransports();
75
- const serviceDefs = { test: TestServiceConstructor() };
76
- const server = await createServer(serverTransport, serviceDefs);
77
- const client = createClient(clientTransport);
78
- const [input, output, close] = await client.test.echo.stream();
79
- input.push({ msg: 'abc', ignore: false });
80
- input.push({ msg: 'def', ignore: true });
81
- input.push({ msg: 'ghi', ignore: false });
82
- input.push({ msg: 'end', ignore: false, end: true });
83
- input.end();
84
- const result1 = await iterNext(output);
85
- assert(result1.ok);
86
- expect(result1.payload).toStrictEqual({ response: 'abc' });
87
- const result2 = await iterNext(output);
88
- assert(result2.ok);
89
- expect(result2.payload).toStrictEqual({ response: 'ghi' });
90
- const result3 = await iterNext(output);
91
- assert(result3.ok);
92
- expect(result3.payload).toStrictEqual({ response: 'end' });
93
- // after the server stream is ended, the client stream should be ended too
94
- const result4 = await output.next();
95
- assert(result4.done);
96
- close();
97
- await testFinishesCleanly({
98
- clientTransports: [clientTransport],
99
- serverTransport,
100
- server,
101
- });
102
- });
103
- test('stream with init message', async () => {
104
- const [clientTransport, serverTransport] = getTransports();
105
- const serviceDefs = { test: TestServiceConstructor() };
106
- const server = await createServer(serverTransport, serviceDefs);
107
- const client = createClient(clientTransport);
108
- const [input, output, close] = await client.test.echoWithPrefix.stream({
109
- prefix: 'test',
110
- });
111
- input.push({ msg: 'abc', ignore: false });
112
- input.push({ msg: 'def', ignore: true });
113
- input.push({ msg: 'ghi', ignore: false });
114
- input.end();
115
- const result1 = await iterNext(output);
116
- assert(result1.ok);
117
- expect(result1.payload).toStrictEqual({ response: 'test abc' });
118
- const result2 = await iterNext(output);
119
- assert(result2.ok);
120
- expect(result2.payload).toStrictEqual({ response: 'test ghi' });
121
- close();
122
- await testFinishesCleanly({
123
- clientTransports: [clientTransport],
124
- serverTransport,
125
- server,
126
- });
127
- });
128
- test('fallible stream', async () => {
129
- const [clientTransport, serverTransport] = getTransports();
130
- const serviceDefs = { test: FallibleServiceConstructor() };
131
- const server = await createServer(serverTransport, serviceDefs);
132
- const client = createClient(clientTransport);
133
- const [input, output, close] = await client.test.echo.stream();
134
- input.push({ msg: 'abc', throwResult: false, throwError: false });
135
- const result1 = await iterNext(output);
136
- assert(result1 && result1.ok);
137
- expect(result1.payload).toStrictEqual({ response: 'abc' });
138
- input.push({ msg: 'def', throwResult: true, throwError: false });
139
- const result2 = await iterNext(output);
140
- assert(result2 && !result2.ok);
141
- expect(result2.payload.code).toStrictEqual(STREAM_ERROR);
142
- input.push({ msg: 'ghi', throwResult: false, throwError: true });
143
- const result3 = await iterNext(output);
144
- assert(result3 && !result3.ok);
145
- expect(result3.payload).toStrictEqual({
146
- code: UNCAUGHT_ERROR,
147
- message: 'some message',
148
- });
149
- close();
150
- await testFinishesCleanly({
151
- clientTransports: [clientTransport],
152
- serverTransport,
153
- server,
154
- });
155
- });
156
- test('subscription', async () => {
157
- const options = { codec };
158
- const serverTransport = new WebSocketServerTransport(webSocketServer, 'SERVER', options);
159
- const client1Transport = new WebSocketClientTransport(() => createLocalWebSocketClient(port), 'client1', 'SERVER', options);
160
- const client2Transport = new WebSocketClientTransport(() => createLocalWebSocketClient(port), 'client2', 'SERVER', options);
161
- const serviceDefs = { test: SubscribableServiceConstructor() };
162
- const server = await createServer(serverTransport, serviceDefs);
163
- const client1 = createClient(client1Transport);
164
- const client2 = createClient(client2Transport);
165
- const [subscription1, close1] = await client1.test.value.subscribe({});
166
- let result = await iterNext(subscription1);
167
- assert(result.ok);
168
- expect(result.payload).toStrictEqual({ result: 0 });
169
- const [subscription2, close2] = await client2.test.value.subscribe({});
170
- result = await iterNext(subscription2);
171
- assert(result.ok);
172
- expect(result.payload).toStrictEqual({ result: 0 });
173
- const add1 = await client1.test.add.rpc({ n: 1 });
174
- assert(add1.ok);
175
- result = await iterNext(subscription1);
176
- assert(result.ok);
177
- expect(result.payload).toStrictEqual({ result: 1 });
178
- result = await iterNext(subscription2);
179
- assert(result.ok);
180
- expect(result.payload).toStrictEqual({ result: 1 });
181
- const add2 = await client2.test.add.rpc({ n: 3 });
182
- assert(add2.ok);
183
- result = await iterNext(subscription1);
184
- assert(result.ok);
185
- expect(result.payload).toStrictEqual({ result: 4 });
186
- result = await iterNext(subscription2);
187
- assert(result.ok);
188
- expect(result.payload).toStrictEqual({ result: 4 });
189
- close1();
190
- close2();
191
- await testFinishesCleanly({
192
- clientTransports: [client1Transport, client2Transport],
193
- serverTransport,
194
- server,
195
- });
196
- });
197
- test('upload', async () => {
198
- const [clientTransport, serverTransport] = getTransports();
199
- const serviceDefs = { uploadable: UploadableServiceConstructor() };
200
- const server = await createServer(serverTransport, serviceDefs);
201
- const client = createClient(clientTransport);
202
- const [addStream, addResult] = await client.uploadable.addMultiple.upload();
203
- addStream.push({ n: 1 });
204
- addStream.push({ n: 2 });
205
- addStream.end();
206
- const result = await addResult;
207
- assert(result.ok);
208
- expect(result.payload).toStrictEqual({ result: 3 });
209
- await testFinishesCleanly({
210
- clientTransports: [clientTransport],
211
- serverTransport,
212
- server,
213
- });
214
- });
215
- test('upload with init message', async () => {
216
- const [clientTransport, serverTransport] = getTransports();
217
- const serviceDefs = { uploadable: UploadableServiceConstructor() };
218
- const server = await createServer(serverTransport, serviceDefs);
219
- const client = createClient(clientTransport);
220
- const [addStream, addResult] = await client.uploadable.addMultipleWithPrefix.upload({
221
- prefix: 'test',
222
- });
223
- addStream.push({ n: 1 });
224
- addStream.push({ n: 2 });
225
- addStream.end();
226
- const result = await addResult;
227
- assert(result.ok);
228
- expect(result.payload).toStrictEqual({ result: 'test 3' });
229
- await testFinishesCleanly({
230
- clientTransports: [clientTransport],
231
- serverTransport,
232
- server,
233
- });
234
- });
235
- test('message order is preserved in the face of disconnects', async () => {
236
- const [clientTransport, serverTransport] = getTransports();
237
- const serviceDefs = { test: OrderingServiceConstructor() };
238
- const server = await createServer(serverTransport, serviceDefs);
239
- const client = createClient(clientTransport);
240
- const expected = [];
241
- for (let i = 0; i < 50; i++) {
242
- expected.push(i);
243
- if (i == 10) {
244
- clientTransport.connections.forEach((conn) => conn.ws.close());
245
- }
246
- if (i == 42) {
247
- clientTransport.connections.forEach((conn) => conn.ws.terminate());
248
- }
249
- await client.test.add.rpc({
250
- n: i,
251
- });
252
- }
253
- const res = await client.test.getAll.rpc({});
254
- assert(res.ok);
255
- expect(res.payload.msgs).toStrictEqual(expected);
256
- await testFinishesCleanly({
257
- clientTransports: [clientTransport],
258
- serverTransport,
259
- server,
260
- });
261
- });
262
- const CONCURRENCY = 10;
263
- test('concurrent rpcs', async () => {
264
- const [clientTransport, serverTransport] = getTransports();
265
- const serviceDefs = { test: OrderingServiceConstructor() };
266
- const server = await createServer(serverTransport, serviceDefs);
267
- const client = createClient(clientTransport);
268
- const promises = [];
269
- for (let i = 0; i < CONCURRENCY; i++) {
270
- promises.push(client.test.add.rpc({ n: i }));
271
- }
272
- for (let i = 0; i < CONCURRENCY; i++) {
273
- const result = await promises[i];
274
- assert(result.ok);
275
- expect(result.payload).toStrictEqual({ n: i });
276
- }
277
- await testFinishesCleanly({
278
- clientTransports: [clientTransport],
279
- serverTransport,
280
- server,
281
- });
282
- });
283
- test('concurrent streams', async () => {
284
- const [clientTransport, serverTransport] = getTransports();
285
- const serviceDefs = { test: TestServiceConstructor() };
286
- const server = await createServer(serverTransport, serviceDefs);
287
- const client = createClient(clientTransport);
288
- const openStreams = [];
289
- for (let i = 0; i < CONCURRENCY; i++) {
290
- const streamHandle = await client.test.echo.stream();
291
- const input = streamHandle[0];
292
- input.push({ msg: `${i}-1`, ignore: false });
293
- input.push({ msg: `${i}-2`, ignore: false });
294
- openStreams.push(streamHandle);
295
- }
296
- for (let i = 0; i < CONCURRENCY; i++) {
297
- const output = openStreams[i][1];
298
- const result1 = await iterNext(output);
299
- assert(result1.ok);
300
- expect(result1.payload).toStrictEqual({ response: `${i}-1` });
301
- const result2 = await iterNext(output);
302
- assert(result2.ok);
303
- expect(result2.payload).toStrictEqual({ response: `${i}-2` });
304
- }
305
- // cleanup
306
- for (let i = 0; i < CONCURRENCY; i++) {
307
- const [_input, _output, close] = openStreams[i];
308
- close();
309
- }
310
- await testFinishesCleanly({
311
- clientTransports: [clientTransport],
312
- serverTransport,
313
- server,
314
- });
315
- });
316
- });
@@ -1,12 +0,0 @@
1
- import { Connection, Transport } from '../../transport';
2
- import { Server } from '../../router';
3
- export declare function ensureTransportIsClean(t: Transport<Connection>): Promise<void>;
4
- export declare function waitUntil<T>(valueGetter: () => T, expected: T, message?: string): Promise<boolean>;
5
- export declare function ensureTransportQueuesAreEventuallyEmpty(t: Transport<Connection>): Promise<void>;
6
- export declare function ensureServerIsClean(s: Server<unknown>): Promise<boolean>;
7
- export declare function testFinishesCleanly({ clientTransports, serverTransport, server, }: Partial<{
8
- clientTransports: Array<Transport<Connection>>;
9
- serverTransport: Transport<Connection>;
10
- server: Server<unknown>;
11
- }>): Promise<void>;
12
- //# sourceMappingURL=cleanup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../../__tests__/fixtures/cleanup.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAOtC,wBAAsB,sBAAsB,CAAC,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,iBAapE;AAED,wBAAsB,SAAS,CAAC,CAAC,EAC/B,WAAW,EAAE,MAAM,CAAC,EACpB,QAAQ,EAAE,CAAC,EACX,OAAO,CAAC,EAAE,MAAM,oBAOjB;AAED,wBAAsB,uCAAuC,CAC3D,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,iBAazB;AAED,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,oBAM3D;AAED,wBAAsB,mBAAmB,CAAC,EACxC,gBAAgB,EAChB,eAAe,EACf,MAAM,GACP,EAAE,OAAO,CAAC;IACT,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/C,eAAe,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;CACzB,CAAC,iBAgBD"}
@@ -1,39 +0,0 @@
1
- import { expect, vi } from 'vitest';
2
- const waitUntilOptions = {
3
- timeout: 250,
4
- interval: 5, // check every 5ms
5
- };
6
- export async function ensureTransportIsClean(t) {
7
- expect(t.state, `transport ${t.clientId} should be closed after the test`).to.not.equal('open');
8
- expect(t.connections, `transport ${t.clientId} should not have open connections after the test`).toStrictEqual(new Map());
9
- expect(t.eventDispatcher.numberOfListeners('message'), `transport ${t.clientId} should not have open message handlers after the test`).equal(0);
10
- }
11
- export async function waitUntil(valueGetter, expected, message) {
12
- return vi
13
- .waitUntil(() => valueGetter() === expected, waitUntilOptions)
14
- .finally(() => {
15
- expect(valueGetter(), message).toEqual(expected);
16
- });
17
- }
18
- export async function ensureTransportQueuesAreEventuallyEmpty(t) {
19
- await waitUntil(() => t.sendQueue.size, 0, `transport ${t.clientId} should not have any messages waiting to send after the test`);
20
- await waitUntil(() => t.sendBuffer.size, 0, `transport ${t.clientId} should not have any un-acked messages after the test`);
21
- }
22
- export async function ensureServerIsClean(s) {
23
- return waitUntil(() => s.streams.size, 0, `server should not have any open streams after the test`);
24
- }
25
- export async function testFinishesCleanly({ clientTransports, serverTransport, server, }) {
26
- if (clientTransports) {
27
- await Promise.all(clientTransports.map((t) => t.close()));
28
- await Promise.all(clientTransports.map(ensureTransportIsClean));
29
- }
30
- // server sits on top of server transport so we clean it up first
31
- if (server) {
32
- await ensureServerIsClean(server);
33
- await server.close();
34
- }
35
- if (serverTransport) {
36
- await serverTransport.close();
37
- await ensureTransportIsClean(serverTransport);
38
- }
39
- }
@@ -1,33 +0,0 @@
1
- {
2
- "data": [
3
- {
4
- "type": "articles",
5
- "id": "1",
6
- "attributes": {
7
- "title": "Example article",
8
- "body": "The shortest article. Ever.",
9
- "created": "2015-05-22T14:56:29.000Z",
10
- "updated": "2015-05-22T14:56:28.000Z"
11
- },
12
- "relationships": {
13
- "author": {
14
- "data": {
15
- "id": "42",
16
- "type": "people"
17
- }
18
- }
19
- }
20
- }
21
- ],
22
- "included": [
23
- {
24
- "type": "people",
25
- "id": "42",
26
- "attributes": {
27
- "name": "John",
28
- "age": 21,
29
- "gender": "male"
30
- }
31
- }
32
- ]
33
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * Represents an observable value that can be subscribed to for changes.
3
- * This should only be used in tests
4
- * @template T - The type of the value being observed.
5
- */
6
- export declare class Observable<T> {
7
- value: T;
8
- private listeners;
9
- constructor(initialValue: T);
10
- /**
11
- * Gets the current value of the observable.
12
- */
13
- get(): T;
14
- /**
15
- * Sets the current value of the observable. All listeners will get an update with this value.
16
- * @param newValue - The new value to set.
17
- */
18
- set(tx: (preValue: T) => T): void;
19
- /**
20
- * Subscribes to changes in the observable value.
21
- * @param listener - A callback function that will be called when the value changes.
22
- * @returns A function that can be called to unsubscribe from further notifications.
23
- */
24
- observe(listener: (val: T) => void): () => boolean;
25
- }
26
- //# sourceMappingURL=observable.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"observable.d.ts","sourceRoot":"","sources":["../../../__tests__/fixtures/observable.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,SAAS,CAAwB;gBAE7B,YAAY,EAAE,CAAC;IAK3B;;OAEG;IACH,GAAG;IAIH;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC;IAM1B;;;;OAIG;IACH,OAAO,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI;CAKnC"}
@@ -1,38 +0,0 @@
1
- /**
2
- * Represents an observable value that can be subscribed to for changes.
3
- * This should only be used in tests
4
- * @template T - The type of the value being observed.
5
- */
6
- export class Observable {
7
- value;
8
- listeners;
9
- constructor(initialValue) {
10
- this.value = initialValue;
11
- this.listeners = new Set();
12
- }
13
- /**
14
- * Gets the current value of the observable.
15
- */
16
- get() {
17
- return this.value;
18
- }
19
- /**
20
- * Sets the current value of the observable. All listeners will get an update with this value.
21
- * @param newValue - The new value to set.
22
- */
23
- set(tx) {
24
- const newValue = tx(this.value);
25
- this.value = newValue;
26
- this.listeners.forEach((listener) => listener(newValue));
27
- }
28
- /**
29
- * Subscribes to changes in the observable value.
30
- * @param listener - A callback function that will be called when the value changes.
31
- * @returns A function that can be called to unsubscribe from further notifications.
32
- */
33
- observe(listener) {
34
- this.listeners.add(listener);
35
- listener(this.get());
36
- return () => this.listeners.delete(listener);
37
- }
38
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=observable.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"observable.test.d.ts","sourceRoot":"","sources":["../../../__tests__/fixtures/observable.test.ts"],"names":[],"mappings":""}
@@ -1,39 +0,0 @@
1
- import { Observable } from './observable';
2
- import { describe, expect, test, vitest } from 'vitest';
3
- describe('Observable', () => {
4
- test('should set initial value correctly', () => {
5
- const initialValue = 10;
6
- const observable = new Observable(initialValue);
7
- expect(observable.value).toBe(initialValue);
8
- });
9
- test('should update value correctly', () => {
10
- const observable = new Observable(10);
11
- const newValue = 20;
12
- observable.set(() => newValue);
13
- expect(observable.value).toBe(newValue);
14
- });
15
- test('should notify listeners when value changes', () => {
16
- const observable = new Observable(10);
17
- const listener = vitest.fn();
18
- observable.observe(listener);
19
- expect(listener).toHaveBeenCalledTimes(1);
20
- const newValue = 20;
21
- observable.set(() => newValue);
22
- expect(listener).toHaveBeenCalledTimes(2);
23
- expect(listener).toHaveBeenCalledWith(newValue);
24
- });
25
- test('should unsubscribe from notifications', () => {
26
- const observable = new Observable(10);
27
- const listener = vitest.fn();
28
- const unsubscribe = observable.observe(listener);
29
- expect(listener).toHaveBeenCalledTimes(1);
30
- const newValue = 20;
31
- observable.set(() => newValue);
32
- expect(listener).toHaveBeenCalledTimes(2);
33
- expect(listener).toHaveBeenCalledWith(newValue);
34
- unsubscribe();
35
- const anotherValue = 30;
36
- observable.set(() => anotherValue);
37
- expect(listener).toHaveBeenCalledTimes(2); // should not be called again after unsubscribing
38
- });
39
- });