@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,30 +0,0 @@
1
- /**
2
- * The context for services/procedures. This is used only on
3
- * the server.
4
- *
5
- * An important detail is that the state prop is always on
6
- * this interface and it shouldn't be changed, removed, or
7
- * extended. This prop is for the state of a service.
8
- *
9
- * You should use declaration merging to extend this interface
10
- * with whatever you need. For example, if you need to access
11
- * a database, you could do:
12
- *
13
- * ```ts
14
- * declare module '@replit/river' {
15
- * interface ServiceContext {
16
- * db: Database;
17
- * }
18
- * }
19
- * ```
20
- */
21
- export interface ServiceContext {
22
- state: object | unknown;
23
- }
24
- /**
25
- * The {@link ServiceContext} with state. This is what is passed to procedures.
26
- */
27
- export type ServiceContextWithState<State extends object | unknown> = ServiceContext & {
28
- state: State;
29
- };
30
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../router/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,CAAC,KAAK,SAAS,MAAM,GAAG,OAAO,IAChE,cAAc,GAAG;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC"}
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../router/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC7D,YAAY,EACV,aAAa,EACb,WAAW,EACX,OAAO,EACP,WAAW,EACX,SAAS,EACT,UAAU,EACV,QAAQ,EACR,SAAS,EACT,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AACxE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC"}
@@ -1,25 +0,0 @@
1
- import { TLiteralString, TNever, TObject, TSchema, TString, TUnion } from '@sinclair/typebox';
2
- export type RiverErrorSchema = TObject<{
3
- code: TLiteralString;
4
- message: TLiteralString | TString;
5
- }> | TObject<{
6
- code: TLiteralString;
7
- message: TLiteralString | TString;
8
- extras: TSchema;
9
- }>;
10
- export type RiverError = TUnion<RiverErrorSchema[]> | RiverErrorSchema | TNever;
11
- export declare const UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
12
- export declare const RiverUncaughtSchema: TObject<{
13
- code: import("@sinclair/typebox").TLiteral<"UNCAUGHT_ERROR">;
14
- message: TString;
15
- }>;
16
- export type Result<T, E> = {
17
- ok: true;
18
- payload: T;
19
- } | {
20
- ok: false;
21
- payload: E;
22
- };
23
- export declare function Ok<T, E>(payload: T): Result<T, E>;
24
- export declare function Err<T, E>(error: E): Result<T, E>;
25
- //# sourceMappingURL=result.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../router/result.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,MAAM,EAEP,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,gBAAgB,GACxB,OAAO,CAAC;IACN,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC;CACnC,CAAC,GACF,OAAO,CAAC;IACN,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC,CAAC;AACP,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC,GAAG,gBAAgB,GAAG,MAAM,CAAC;AAEhF,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAC/C,eAAO,MAAM,mBAAmB;;;EAG9B,CAAC;AAEH,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IACnB;IACE,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,CAAC,CAAC;CACZ,GACD;IACE,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,CAAC,CAAC;CACZ,CAAC;AAEN,wBAAgB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAKjD;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAKhD"}
@@ -1,18 +0,0 @@
1
- import { Type, } from '@sinclair/typebox';
2
- export const UNCAUGHT_ERROR = 'UNCAUGHT_ERROR';
3
- export const RiverUncaughtSchema = Type.Object({
4
- code: Type.Literal(UNCAUGHT_ERROR),
5
- message: Type.String(),
6
- });
7
- export function Ok(payload) {
8
- return {
9
- ok: true,
10
- payload,
11
- };
12
- }
13
- export function Err(error) {
14
- return {
15
- ok: false,
16
- payload: error,
17
- };
18
- }
@@ -1,39 +0,0 @@
1
- import { Static } from '@sinclair/typebox';
2
- import { Connection, Transport } from '../transport/transport';
3
- import { AnyProcedure, AnyService, PayloadType } from './builder';
4
- import type { Pushable } from 'it-pushable';
5
- import { TransportMessage } from '../transport/message';
6
- import { ServiceContext } from './context';
7
- import { Result, RiverError } from './result';
8
- /**
9
- * Represents a server with a set of services. Use {@link createServer} to create it.
10
- * @template Services - The type of services provided by the server.
11
- */
12
- export interface Server<Services> {
13
- services: Services;
14
- streams: Map<string, ProcStream>;
15
- close(): Promise<void>;
16
- }
17
- interface ProcStream {
18
- id: string;
19
- serviceName: string;
20
- procedureName: string;
21
- procedure: AnyProcedure;
22
- incoming: Pushable<TransportMessage>;
23
- outgoing: Pushable<TransportMessage<Result<Static<PayloadType>, Static<RiverError>>>>;
24
- promises: {
25
- outputHandler: Promise<unknown>;
26
- inputHandler: Promise<unknown>;
27
- };
28
- }
29
- /**
30
- * Creates a server instance that listens for incoming messages from a transport and routes them to the appropriate service and procedure.
31
- * The server tracks the state of each service along with open streams and the extended context object.
32
- * @param transport - The transport to listen to.
33
- * @param services - An object containing all the services to be registered on the server.
34
- * @param extendedContext - An optional object containing additional context to be passed to all services.
35
- * @returns A promise that resolves to a server instance with the registered services.
36
- */
37
- export declare function createServer<Services extends Record<string, AnyService>>(transport: Transport<Connection>, services: Services, extendedContext?: Omit<ServiceContext, 'state'>): Promise<Server<Services>>;
38
- export {};
39
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../router/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAGL,gBAAgB,EAKjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,cAAc,EAA2B,MAAM,WAAW,CAAC;AAGpE,OAAO,EAEL,MAAM,EACN,UAAU,EAGX,MAAM,UAAU,CAAC;AAElB;;;GAGG;AACH,MAAM,WAAW,MAAM,CAAC,QAAQ;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACrC,QAAQ,EAAE,QAAQ,CAChB,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAClE,CAAC;IACF,QAAQ,EAAE;QACR,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAChC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;KAChC,CAAC;CACH;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAC5E,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,EAChC,QAAQ,EAAE,QAAQ,EAClB,eAAe,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC,GAC9C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAqQ3B"}
@@ -1,217 +0,0 @@
1
- import { pushable } from 'it-pushable';
2
- import { ControlMessagePayloadSchema, isStreamClose, isStreamOpen, reply, closeStream, } from '../transport/message';
3
- import { log } from '../logging';
4
- import { Value } from '@sinclair/typebox/value';
5
- import { Err, UNCAUGHT_ERROR, } from './result';
6
- /**
7
- * Creates a server instance that listens for incoming messages from a transport and routes them to the appropriate service and procedure.
8
- * The server tracks the state of each service along with open streams and the extended context object.
9
- * @param transport - The transport to listen to.
10
- * @param services - An object containing all the services to be registered on the server.
11
- * @param extendedContext - An optional object containing additional context to be passed to all services.
12
- * @returns A promise that resolves to a server instance with the registered services.
13
- */
14
- export async function createServer(transport, services, extendedContext) {
15
- const contextMap = new Map();
16
- // map of streamId to ProcStream
17
- const streamMap = new Map();
18
- async function cleanupStream(id) {
19
- const stream = streamMap.get(id);
20
- if (!stream) {
21
- return;
22
- }
23
- stream.incoming.end();
24
- await stream.promises.inputHandler;
25
- stream.outgoing.end();
26
- await stream.promises.outputHandler;
27
- streamMap.delete(id);
28
- }
29
- function getContext(service) {
30
- const context = contextMap.get(service);
31
- if (!context) {
32
- const err = `${transport.clientId} -- no context found for ${service.name}`;
33
- log?.error(err);
34
- throw new Error(err);
35
- }
36
- return context;
37
- }
38
- // populate the context map
39
- for (const service of Object.values(services)) {
40
- contextMap.set(service, { ...extendedContext, state: service.state });
41
- }
42
- const handler = async (message) => {
43
- if (message.to !== transport.clientId) {
44
- log?.info(`${transport.clientId} -- got msg with destination that isn't the server, ignoring`);
45
- return;
46
- }
47
- const streamIdx = message.streamId;
48
- const procStream = streamMap.get(streamIdx);
49
- if (procStream) {
50
- // If the stream is a continuation, we do not admit the init messages.
51
- if (Value.Check(procStream.procedure.input, message.payload)) {
52
- procStream.incoming.push(message);
53
- }
54
- else if (!Value.Check(ControlMessagePayloadSchema, message.payload)) {
55
- log?.error(`${transport.clientId} -- procedure ${procStream.serviceName}.${procStream.procedureName} received invalid payload: ${JSON.stringify(message.payload)}`);
56
- }
57
- if (isStreamClose(message.controlFlags)) {
58
- await cleanupStream(streamIdx);
59
- }
60
- return;
61
- }
62
- if (!isStreamOpen(message.controlFlags)) {
63
- log?.warn(`${transport.clientId} -- couldn't find a matching procedure stream for ${message.serviceName}.${message.procedureName}:${message.streamId}`);
64
- return;
65
- }
66
- if (!message.serviceName || !(message.serviceName in services)) {
67
- log?.warn(`${transport.clientId} -- couldn't find service ${message.serviceName}`);
68
- return;
69
- }
70
- const service = services[message.serviceName];
71
- const serviceContext = getContext(service);
72
- if (!message.procedureName ||
73
- !(message.procedureName in service.procedures)) {
74
- log?.warn(`${transport.clientId} -- couldn't find a matching procedure for ${message.serviceName}.${message.procedureName}`);
75
- return;
76
- }
77
- const procedure = service.procedures[message.procedureName];
78
- const procHasInitMessage = 'init' in procedure;
79
- const incoming = pushable({ objectMode: true });
80
- const outgoing = pushable({ objectMode: true });
81
- const outputHandler =
82
- // sending outgoing messages back to client
83
- (async () => {
84
- for await (const response of outgoing) {
85
- transport.send(response);
86
- }
87
- // we ended, send a close bit back to the client
88
- // only subscriptions and streams have streams the
89
- // handler can close
90
- if (procedure.type === 'subscription' || procedure.type === 'stream') {
91
- transport.send(closeStream(transport.clientId, message.from, message.streamId));
92
- }
93
- })();
94
- function errorHandler(err) {
95
- const errorMsg = err instanceof Error ? err.message : `[coerced to error] ${err}`;
96
- log?.error(`${transport.clientId} -- procedure ${message.serviceName}.${message.procedureName}:${message.streamId} threw an error: ${errorMsg}`);
97
- outgoing.push(reply(message, Err({
98
- code: UNCAUGHT_ERROR,
99
- message: errorMsg,
100
- })));
101
- }
102
- // pump incoming message stream -> handler -> outgoing message stream
103
- let inputHandler;
104
- if (procedure.type === 'stream') {
105
- if (procHasInitMessage) {
106
- inputHandler = (async () => {
107
- const initMessage = await incoming.next();
108
- if (initMessage.done) {
109
- return;
110
- }
111
- return procedure
112
- .handler(serviceContext, initMessage.value, incoming, outgoing)
113
- .catch(errorHandler);
114
- })();
115
- }
116
- else {
117
- inputHandler = procedure
118
- .handler(serviceContext, incoming, outgoing)
119
- .catch(errorHandler);
120
- }
121
- }
122
- else if (procedure.type === 'rpc') {
123
- inputHandler = (async () => {
124
- const inputMessage = await incoming.next();
125
- if (inputMessage.done) {
126
- return;
127
- }
128
- try {
129
- const outputMessage = await procedure.handler(serviceContext, inputMessage.value);
130
- outgoing.push(outputMessage);
131
- }
132
- catch (err) {
133
- errorHandler(err);
134
- }
135
- })();
136
- }
137
- else if (procedure.type === 'subscription') {
138
- inputHandler = (async () => {
139
- const inputMessage = await incoming.next();
140
- if (inputMessage.done) {
141
- return;
142
- }
143
- try {
144
- await procedure.handler(serviceContext, inputMessage.value, outgoing);
145
- }
146
- catch (err) {
147
- errorHandler(err);
148
- }
149
- })();
150
- }
151
- else if (procedure.type === 'upload') {
152
- if (procHasInitMessage) {
153
- inputHandler = (async () => {
154
- const initMessage = await incoming.next();
155
- if (initMessage.done) {
156
- return;
157
- }
158
- try {
159
- const outputMessage = await procedure.handler(serviceContext, initMessage.value, incoming);
160
- outgoing.push(outputMessage);
161
- }
162
- catch (err) {
163
- errorHandler(err);
164
- }
165
- })();
166
- }
167
- else {
168
- inputHandler = (async () => {
169
- try {
170
- const outputMessage = await procedure.handler(serviceContext, incoming);
171
- outgoing.push(outputMessage);
172
- }
173
- catch (err) {
174
- errorHandler(err);
175
- }
176
- })();
177
- }
178
- }
179
- else {
180
- // procedure is inferred to be never here as this is not a valid procedure type
181
- // we cast just to log
182
- log?.warn(`${transport.clientId} -- got request for invalid procedure type ${procedure.type} at ${message.serviceName}.${message.procedureName}`);
183
- return;
184
- }
185
- streamMap.set(streamIdx, {
186
- id: message.streamId,
187
- incoming,
188
- outgoing,
189
- serviceName: message.serviceName,
190
- procedureName: message.procedureName,
191
- procedure,
192
- promises: { inputHandler, outputHandler },
193
- });
194
- // This is the first message, so we parse is as the initialization message, if supplied.
195
- if ((!procHasInitMessage && Value.Check(procedure.input, message.payload)) ||
196
- (procHasInitMessage && Value.Check(procedure.init, message.payload))) {
197
- incoming.push(message);
198
- }
199
- else if (!Value.Check(ControlMessagePayloadSchema, message.payload)) {
200
- log?.error(`${transport.clientId} -- procedure ${message.serviceName}.${message.procedureName} received invalid payload: ${JSON.stringify(message.payload)}`);
201
- }
202
- if (isStreamClose(message.controlFlags)) {
203
- await cleanupStream(streamIdx);
204
- }
205
- };
206
- transport.addEventListener('message', handler);
207
- return {
208
- services,
209
- streams: streamMap,
210
- async close() {
211
- transport.removeEventListener('message', handler);
212
- for (const streamIdx of streamMap.keys()) {
213
- await cleanupStream(streamIdx);
214
- }
215
- },
216
- };
217
- }
@@ -1,19 +0,0 @@
1
- import { OpaqueTransportMessage } from './message';
2
- import { Connection } from './transport';
3
- export interface EventMap {
4
- message: OpaqueTransportMessage;
5
- connectionStatus: {
6
- status: 'connect' | 'disconnect';
7
- conn: Connection;
8
- };
9
- }
10
- export type EventTypes = keyof EventMap;
11
- export type EventHandler<K extends EventTypes> = (event: EventMap[K]) => void;
12
- export declare class EventDispatcher<T extends EventTypes> {
13
- private eventListeners;
14
- numberOfListeners<K extends T>(eventType: K): number;
15
- addEventListener<K extends T>(eventType: K, handler: EventHandler<K>): void;
16
- removeEventListener<K extends T>(eventType: K, handler: EventHandler<K>): void;
17
- dispatchEvent<K extends T>(eventType: K, event: EventMap[K]): void;
18
- }
19
- //# sourceMappingURL=events.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../transport/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,sBAAsB,CAAC;IAChC,gBAAgB,EAAE;QAChB,MAAM,EAAE,SAAS,GAAG,YAAY,CAAC;QACjC,IAAI,EAAE,UAAU,CAAC;KAClB,CAAC;CACH;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC;AACxC,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAE9E,qBAAa,eAAe,CAAC,CAAC,SAAS,UAAU;IAC/C,OAAO,CAAC,cAAc,CAA2C;IAEjE,iBAAiB,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IAI3C,gBAAgB,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAQpE,mBAAmB,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;IAOvE,aAAa,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;CAQ5D"}
@@ -1,26 +0,0 @@
1
- export class EventDispatcher {
2
- eventListeners = {};
3
- numberOfListeners(eventType) {
4
- return this.eventListeners[eventType]?.size ?? 0;
5
- }
6
- addEventListener(eventType, handler) {
7
- if (!this.eventListeners[eventType]) {
8
- this.eventListeners[eventType] = new Set();
9
- }
10
- this.eventListeners[eventType]?.add(handler);
11
- }
12
- removeEventListener(eventType, handler) {
13
- const handlers = this.eventListeners[eventType];
14
- if (handlers) {
15
- this.eventListeners[eventType]?.delete(handler);
16
- }
17
- }
18
- dispatchEvent(eventType, event) {
19
- const handlers = this.eventListeners[eventType];
20
- if (handlers) {
21
- for (const handler of handlers) {
22
- handler(event);
23
- }
24
- }
25
- }
26
- }
@@ -1,33 +0,0 @@
1
- /// <reference types="node" />
2
- import { Codec } from '../../../codec';
3
- import { TransportClientId } from '../../message';
4
- import { Connection, Transport } from '../../transport';
5
- export declare class StdioConnection extends Connection {
6
- output: NodeJS.WritableStream;
7
- constructor(transport: Transport<StdioConnection>, connectedTo: TransportClientId, output: NodeJS.WritableStream);
8
- send(payload: Uint8Array): boolean;
9
- close(): Promise<void>;
10
- }
11
- interface Options {
12
- codec: Codec;
13
- }
14
- /**
15
- * A transport implementation that uses standard input and output streams.
16
- * @extends Transport
17
- */
18
- export declare class StdioTransport extends Transport<StdioConnection> {
19
- clientId: TransportClientId;
20
- input: NodeJS.ReadableStream;
21
- output: NodeJS.WritableStream;
22
- /**
23
- * Constructs a new StdioTransport instance.
24
- * @param clientId - The ID of the client associated with this transport.
25
- * @param input - The readable stream to use as input. Defaults to process.stdin.
26
- * @param output - The writable stream to use as output. Defaults to process.stdout.
27
- */
28
- constructor(clientId: TransportClientId, input?: NodeJS.ReadableStream, output?: NodeJS.WritableStream, providedOptions?: Partial<Options>);
29
- setupConnectionStatusListeners(): void;
30
- createNewConnection(to: TransportClientId): Promise<void>;
31
- }
32
- export {};
33
- //# sourceMappingURL=stdio.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["../../../../transport/impls/stdio/stdio.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAGvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAKxD,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;gBAG5B,SAAS,EAAE,SAAS,CAAC,eAAe,CAAC,EACrC,WAAW,EAAE,iBAAiB,EAC9B,MAAM,EAAE,MAAM,CAAC,cAAc;IAM/B,IAAI,CAAC,OAAO,EAAE,UAAU;IAOlB,KAAK;CAGZ;AAED,UAAU,OAAO;IACf,KAAK,EAAE,KAAK,CAAC;CACd;AAMD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,SAAS,CAAC,eAAe,CAAC;IAC5D,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC,cAAc,CAAiB;IAC7C,MAAM,EAAE,MAAM,CAAC,cAAc,CAAkB;IAE/C;;;;;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;IAUpC,8BAA8B,IAAI,IAAI;IAwBhC,mBAAmB,CAAC,EAAE,EAAE,iBAAiB;CAShD"}
@@ -1,75 +0,0 @@
1
- import { NaiveJsonCodec } from '../../../codec/json';
2
- import { log } from '../../../logging';
3
- import { Connection, Transport } from '../../transport';
4
- import readline from 'readline';
5
- const newlineBuff = new TextEncoder().encode('\n');
6
- export class StdioConnection extends Connection {
7
- output;
8
- constructor(transport, connectedTo, output) {
9
- super(transport, connectedTo);
10
- this.output = output;
11
- }
12
- send(payload) {
13
- const out = new Uint8Array(payload.length + newlineBuff.length);
14
- out.set(payload, 0);
15
- out.set(newlineBuff, payload.length);
16
- return this.output.write(out);
17
- }
18
- async close() {
19
- this.output.end();
20
- }
21
- }
22
- const defaultOptions = {
23
- codec: NaiveJsonCodec,
24
- };
25
- /**
26
- * A transport implementation that uses standard input and output streams.
27
- * @extends Transport
28
- */
29
- export class StdioTransport extends Transport {
30
- clientId;
31
- input = process.stdin;
32
- output = process.stdout;
33
- /**
34
- * Constructs a new StdioTransport instance.
35
- * @param clientId - The ID of the client associated with this transport.
36
- * @param input - The readable stream to use as input. Defaults to process.stdin.
37
- * @param output - The writable stream to use as output. Defaults to process.stdout.
38
- */
39
- constructor(clientId, input = process.stdin, output = process.stdout, providedOptions) {
40
- const options = { ...defaultOptions, ...providedOptions };
41
- super(options.codec, clientId);
42
- this.clientId = clientId;
43
- this.input = input;
44
- this.output = output;
45
- this.setupConnectionStatusListeners();
46
- }
47
- setupConnectionStatusListeners() {
48
- let conn = undefined;
49
- const rl = readline.createInterface({
50
- input: this.input,
51
- });
52
- const encoder = new TextEncoder();
53
- rl.on('line', (msg) => {
54
- const parsedMsg = this.parseMsg(encoder.encode(msg));
55
- if (parsedMsg && !this.connections.has(parsedMsg.from)) {
56
- conn = new StdioConnection(this, parsedMsg.from, this.output);
57
- this.onConnect(conn);
58
- }
59
- this.handleMsg(parsedMsg);
60
- });
61
- rl.on('close', () => {
62
- if (conn) {
63
- this.onDisconnect(conn);
64
- }
65
- });
66
- }
67
- async createNewConnection(to) {
68
- if (this.state === 'destroyed') {
69
- throw new Error('cant reopen a destroyed connection');
70
- }
71
- log?.info(`${this.clientId} -- establishing a new stream to ${to}`);
72
- const conn = new StdioConnection(this, to, this.output);
73
- this.onConnect(conn);
74
- }
75
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=stdio.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"stdio.test.d.ts","sourceRoot":"","sources":["../../../../transport/impls/stdio/stdio.test.ts"],"names":[],"mappings":""}
@@ -1,25 +0,0 @@
1
- import { describe, test, expect } from 'vitest';
2
- import stream from 'node:stream';
3
- import { StdioTransport } from './stdio';
4
- import { waitForMessage } from '../..';
5
- import { payloadToTransportMessage } from '../../../util/testHelpers';
6
- import { ensureTransportIsClean } from '../../../__tests__/fixtures/cleanup';
7
- describe('sending and receiving across node streams works', () => {
8
- test('basic send/receive', async () => {
9
- const clientToServer = new stream.PassThrough();
10
- const serverToClient = new stream.PassThrough();
11
- const serverTransport = new StdioTransport('abc', clientToServer, serverToClient);
12
- const clientTransport = new StdioTransport('def', serverToClient, clientToServer);
13
- const msg = {
14
- msg: 'cool',
15
- test: 123,
16
- };
17
- const p = waitForMessage(serverTransport);
18
- clientTransport.send(payloadToTransportMessage(msg, 'stream', clientTransport.clientId, serverTransport.clientId));
19
- await expect(p).resolves.toStrictEqual(msg);
20
- await clientTransport.close();
21
- await serverTransport.close();
22
- await ensureTransportIsClean(clientTransport);
23
- await ensureTransportIsClean(serverTransport);
24
- });
25
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../transport/impls/ws/client.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,UAAU,OAAO;IACf,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;CACd;AAQD,KAAK,eAAe,GAAG;IAAE,EAAE,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;GAIG;AACH,qBAAa,wBAAyB,SAAQ,SAAS,CAAC,mBAAmB,CAAC;IAC1E;;OAEG;IACH,QAAQ,EAAE,CAAC,EAAE,EAAE,iBAAiB,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAE5B,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IAEpE;;;;;OAKG;gBAED,QAAQ,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,EAClC,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IAWpC,8BAA8B,IAAI,IAAI;IAIhC,mBAAmB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,SAAI;IAuEjD;;OAEG;IACG,IAAI;CAGX"}
@@ -1,11 +0,0 @@
1
- /// <reference types="ws" />
2
- import { TransportClientId } from '../../message';
3
- import { Connection, Transport } from '../../transport';
4
- import WebSocket from 'isomorphic-ws';
5
- export declare class WebSocketConnection extends Connection {
6
- ws: WebSocket;
7
- constructor(transport: Transport<WebSocketConnection>, connectedTo: TransportClientId, ws: WebSocket);
8
- send(payload: Uint8Array): boolean;
9
- close(): Promise<void>;
10
- }
11
- //# sourceMappingURL=connection.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../../../transport/impls/ws/connection.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,SAAS,MAAM,eAAe,CAAC;AAEtC,qBAAa,mBAAoB,SAAQ,UAAU;IACjD,EAAE,EAAE,SAAS,CAAC;gBAGZ,SAAS,EAAE,SAAS,CAAC,mBAAmB,CAAC,EACzC,WAAW,EAAE,iBAAiB,EAC9B,EAAE,EAAE,SAAS;IAUf,IAAI,CAAC,OAAO,EAAE,UAAU;IASlB,KAAK;CAGZ"}
@@ -1,23 +0,0 @@
1
- import { Connection } from '../../transport';
2
- export class WebSocketConnection extends Connection {
3
- ws;
4
- constructor(transport, connectedTo, ws) {
5
- super(transport, connectedTo);
6
- this.ws = ws;
7
- ws.binaryType = 'arraybuffer';
8
- // take over the onmessage for this websocket
9
- this.ws.onmessage = (msg) => transport.onMessage(msg.data);
10
- }
11
- send(payload) {
12
- if (this.ws.readyState === this.ws.OPEN) {
13
- this.ws.send(payload);
14
- return true;
15
- }
16
- else {
17
- return false;
18
- }
19
- }
20
- async close() {
21
- this.ws.close();
22
- }
23
- }
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../transport/impls/ws/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAkB,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,UAAU,OAAO;IACf,KAAK,EAAE,KAAK,CAAC;CACd;AAMD,qBAAa,wBAAyB,SAAQ,SAAS,CAAC,mBAAmB,CAAC;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,iBAAiB,CAAC;gBAG1B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,iBAAiB,EAC3B,eAAe,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;IASpC,8BAA8B,IAAI,IAAI;IAiChC,mBAAmB,CAAC,EAAE,EAAE,MAAM;CAKrC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ws.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ws.test.d.ts","sourceRoot":"","sources":["../../../../transport/impls/ws/ws.test.ts"],"names":[],"mappings":""}