@replit/river 0.10.13 → 0.12.0

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 (83) hide show
  1. package/README.md +28 -8
  2. package/dist/{builder-1f26296b.d.ts → builder-c593de11.d.ts} +14 -13
  3. package/dist/{chunk-3JGVFWKQ.js → chunk-24O3BKZA.js} +205 -180
  4. package/dist/chunk-4HOR4NUO.js +40 -0
  5. package/dist/chunk-ANGOKBE5.js +708 -0
  6. package/dist/{chunk-R6H2BIMC.js → chunk-GZ7HCLLM.js} +31 -7
  7. package/dist/{chunk-T7M7OKPE.js → chunk-H4BYJELI.js} +5 -1
  8. package/dist/chunk-IIBVKYDB.js +62 -0
  9. package/dist/chunk-IUDKWAOK.js +47 -0
  10. package/dist/chunk-WTOIOXB7.js +125 -0
  11. package/dist/chunk-XOTIAXAH.js +44 -0
  12. package/dist/codec/index.cjs +13 -7
  13. package/dist/codec/index.js +2 -4
  14. package/dist/connection-2956a1c5.d.ts +17 -0
  15. package/dist/connection-aaea7c88.d.ts +15 -0
  16. package/dist/connection-cd963ed5.d.ts +18 -0
  17. package/dist/index-d91775d9.d.ts +442 -0
  18. package/dist/logging/index.cjs +8 -3
  19. package/dist/logging/index.d.cts +6 -1
  20. package/dist/logging/index.d.ts +6 -1
  21. package/dist/logging/index.js +5 -3
  22. package/dist/messageFraming-b200ef25.d.ts +20 -0
  23. package/dist/router/index.cjs +249 -211
  24. package/dist/router/index.d.cts +6 -7
  25. package/dist/router/index.d.ts +6 -7
  26. package/dist/router/index.js +3 -3
  27. package/dist/transport/impls/stdio/client.cjs +891 -0
  28. package/dist/transport/impls/stdio/client.d.cts +27 -0
  29. package/dist/transport/impls/stdio/client.d.ts +27 -0
  30. package/dist/transport/impls/stdio/client.js +42 -0
  31. package/dist/transport/impls/stdio/server.cjs +861 -0
  32. package/dist/transport/impls/stdio/server.d.cts +25 -0
  33. package/dist/transport/impls/stdio/server.d.ts +25 -0
  34. package/dist/transport/impls/stdio/server.js +33 -0
  35. package/dist/transport/impls/uds/client.cjs +893 -0
  36. package/dist/transport/impls/uds/client.d.cts +16 -0
  37. package/dist/transport/impls/uds/client.d.ts +16 -0
  38. package/dist/transport/impls/uds/client.js +44 -0
  39. package/dist/transport/impls/uds/server.cjs +863 -0
  40. package/dist/transport/impls/uds/server.d.cts +16 -0
  41. package/dist/transport/impls/uds/server.d.ts +16 -0
  42. package/dist/transport/impls/uds/server.js +39 -0
  43. package/dist/transport/impls/ws/client.cjs +587 -248
  44. package/dist/transport/impls/ws/client.d.cts +6 -21
  45. package/dist/transport/impls/ws/client.d.ts +6 -21
  46. package/dist/transport/impls/ws/client.js +77 -7
  47. package/dist/transport/impls/ws/server.cjs +541 -194
  48. package/dist/transport/impls/ws/server.d.cts +6 -10
  49. package/dist/transport/impls/ws/server.d.ts +6 -10
  50. package/dist/transport/impls/ws/server.js +31 -8
  51. package/dist/transport/index.cjs +652 -129
  52. package/dist/transport/index.d.cts +3 -276
  53. package/dist/transport/index.d.ts +3 -276
  54. package/dist/transport/index.js +13 -10
  55. package/dist/util/testHelpers.cjs +40 -602
  56. package/dist/util/testHelpers.d.cts +18 -37
  57. package/dist/util/testHelpers.d.ts +18 -37
  58. package/dist/util/testHelpers.js +27 -47
  59. package/package.json +29 -14
  60. package/dist/chunk-3MQETIGZ.js +0 -80
  61. package/dist/chunk-5IC5XMWK.js +0 -140
  62. package/dist/chunk-L7D75G4K.js +0 -29
  63. package/dist/chunk-LQXPKF3A.js +0 -282
  64. package/dist/chunk-PJ2EUO7O.js +0 -63
  65. package/dist/chunk-WVT5QXMZ.js +0 -20
  66. package/dist/chunk-ZE4MX7DF.js +0 -75
  67. package/dist/connection-2529fc14.d.ts +0 -10
  68. package/dist/connection-316d6e3a.d.ts +0 -10
  69. package/dist/connection-8e19874c.d.ts +0 -11
  70. package/dist/connection-f7688cc1.d.ts +0 -11
  71. package/dist/transport/impls/stdio/stdio.cjs +0 -508
  72. package/dist/transport/impls/stdio/stdio.d.cts +0 -26
  73. package/dist/transport/impls/stdio/stdio.d.ts +0 -26
  74. package/dist/transport/impls/stdio/stdio.js +0 -70
  75. package/dist/transport/impls/unixsocket/client.cjs +0 -506
  76. package/dist/transport/impls/unixsocket/client.d.cts +0 -16
  77. package/dist/transport/impls/unixsocket/client.d.ts +0 -16
  78. package/dist/transport/impls/unixsocket/client.js +0 -67
  79. package/dist/transport/impls/unixsocket/server.cjs +0 -510
  80. package/dist/transport/impls/unixsocket/server.d.cts +0 -18
  81. package/dist/transport/impls/unixsocket/server.d.ts +0 -18
  82. package/dist/transport/impls/unixsocket/server.js +0 -73
  83. /package/dist/{chunk-ORAG7IAU.js → chunk-5IZ2UHWV.js} +0 -0
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # river - Streaming Remote Procedure Calls
1
+ # river - Long-lived Streaming Remote Procedure Calls
2
2
 
3
3
  It's like tRPC/gRPC but with
4
4
 
@@ -7,6 +7,7 @@ It's like tRPC/gRPC but with
7
7
  - service multiplexing
8
8
  - result types and error handling
9
9
  - snappy DX (no code-generation)
10
+ - transparent reconnect support for long-lived sessions
10
11
  - over any transport (WebSockets, stdio, Unix Domain Socket out of the box)
11
12
 
12
13
  ## Installation
@@ -32,6 +33,8 @@ npm i ws isomorphic-ws
32
33
  - `subscription` whose handler has a signature of `Input -> Pushable<Result<Output, Error>>`.
33
34
  - `stream` whose handler has a signature of `AsyncIterableIterator<Input> -> Pushable<Result<Output, Error>>`.
34
35
  - Transport: manages the lifecycle (creation/deletion) of connections and multiplexing read/writes from clients. Both the client and the server must be passed in a subclass of `Transport` to work.
36
+ - Connection: the actual raw underlying transport connection
37
+ - Session: a higher-level abstraction that operates over the span of potentially multiple transport-level connections
35
38
  - Codec: encodes messages between clients/servers before the transport sends it across the wire.
36
39
 
37
40
  ### A basic router
@@ -110,6 +113,8 @@ if (result.ok) {
110
113
  }
111
114
  ```
112
115
 
116
+ ### Logging
117
+
113
118
  To add logging,
114
119
 
115
120
  ```ts
@@ -119,7 +124,20 @@ bindLogger(console.log);
119
124
  setLevel('info');
120
125
  ```
121
126
 
122
- To listen for connection status changes,
127
+ ### Connection Status
128
+
129
+ River define two types of reconnects:
130
+
131
+ 1. Transparent reconnects: we lost the connection temporarily and reconnected without losing any messages. To the application level, nothing happened.
132
+ 2. Hard reconnect: we've lost all server state and the client should setup the world again.
133
+
134
+ We can listen for transparent reconnects via the `connectionStatus` events but realistically
135
+ no applications should need to listen for this unless it is for debug purposes. Hard reconnects
136
+ are signalled via `sessionStatus` events.
137
+
138
+ If your application is stateful on either the server or the client, the service consumer _should_
139
+ wrap all the client-side setup with `transport.addEventListener('sessionStatus', (evt) => ...)` to
140
+ do appropriate setup and teardown.
123
141
 
124
142
  ```ts
125
143
  transport.addEventListener('connectionStatus', (evt) => {
@@ -129,13 +147,15 @@ transport.addEventListener('connectionStatus', (evt) => {
129
147
  // do something else
130
148
  }
131
149
  });
132
- ```
133
150
 
134
- > [!note] WebSocket connection behaviour
135
- > WebSocket is an idle protocol. This means that when the underlying connection drops, the WebSocket
136
- > may still think it is still connected (e.g. turning off the network via devtools).
137
- > You can use `window.addEventListener('online', ...);` and `window.addEventListener('offline', ...);` to
138
- > know if you need to recreate the transport.
151
+ transport.addEventListener('sessionStatus', (evt) => {
152
+ if (evt.status === 'connect') {
153
+ // do something
154
+ } else if (evt.status === 'disconnect') {
155
+ // do something else
156
+ }
157
+ });
158
+ ```
139
159
 
140
160
  ### Further examples
141
161
 
@@ -22,25 +22,24 @@ import { Pushable } from 'it-pushable';
22
22
  * ```
23
23
  */
24
24
  interface ServiceContext {
25
- state: object | unknown;
26
25
  }
27
26
  /**
28
27
  * The {@link ServiceContext} with state. This is what is passed to procedures.
29
28
  */
30
- type ServiceContextWithState<State extends object | unknown> = ServiceContext & {
29
+ type ServiceContextWithState<State> = ServiceContext & {
31
30
  state: State;
32
31
  };
33
32
 
34
33
  type TLiteralString = TLiteral<string>;
35
34
  type RiverErrorSchema = TObject<{
36
- code: TLiteralString | TUnion<TLiteralString[]>;
35
+ code: TLiteralString | TUnion<Array<TLiteralString>>;
37
36
  message: TLiteralString | TString;
38
37
  }> | TObject<{
39
- code: TLiteralString | TUnion<TLiteralString[]>;
38
+ code: TLiteralString | TUnion<Array<TLiteralString>>;
40
39
  message: TLiteralString | TString;
41
40
  extras: TSchema;
42
41
  }>;
43
- type RiverError = TUnion<RiverErrorSchema[]> | RiverErrorSchema | TNever;
42
+ type RiverError = TUnion<Array<RiverErrorSchema>> | RiverErrorSchema | TNever;
44
43
  declare const UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
45
44
  declare const RiverUncaughtSchema: TObject<{
46
45
  code: TUnion<[TLiteral<"UNCAUGHT_ERROR">, TLiteral<"UNEXPECTED_DISCONNECT">]>;
@@ -80,7 +79,7 @@ interface Service<Name extends string, State extends object, Procs extends ProcL
80
79
  state: State;
81
80
  procedures: Procs;
82
81
  }
83
- type AnyService = Service<string, object, any>;
82
+ type AnyService = Service<string, object, ProcListing>;
84
83
  /**
85
84
  * Serializes a service object into its corresponding JSON Schema Draft 7 type.
86
85
  * @param {AnyService} s - The service object to serialize.
@@ -99,14 +98,16 @@ type ProcHandler<S extends AnyService, ProcName extends keyof S['procedures']> =
99
98
  * @template ProcName - The name of the procedure.
100
99
  */
101
100
  type ProcHasInit<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName] extends {
102
- init: any;
101
+ init: TObject;
103
102
  } ? true : false;
104
103
  /**
105
104
  * Helper to get the type definition for the procedure init type of a service.
106
105
  * @template S - The service.
107
106
  * @template ProcName - The name of the procedure.
108
107
  */
109
- type ProcInit<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['init'];
108
+ type ProcInit<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName] extends {
109
+ init: TObject;
110
+ } ? S['procedures'][ProcName]['init'] : never;
110
111
  /**
111
112
  * Helper to get the type definition for the procedure input of a service.
112
113
  * @template S - The service.
@@ -131,7 +132,7 @@ type ProcErrors<S extends AnyService, ProcName extends keyof S['procedures']> =
131
132
  * @template ProcName - The name of the procedure.
132
133
  */
133
134
  type ProcType<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['type'];
134
- type PayloadType = TObject | TUnion<TObject[]>;
135
+ type PayloadType = TObject | TUnion<Array<TObject>>;
135
136
  /**
136
137
  * Defines a Procedure type that can be either an RPC or a stream procedure.
137
138
  * @template State - The TypeBox schema of the state object.
@@ -140,7 +141,7 @@ type PayloadType = TObject | TUnion<TObject[]>;
140
141
  * @template O - The TypeBox schema of the output object.
141
142
  * @template Init - The TypeBox schema of the input initialization object.
142
143
  */
143
- type Procedure<State extends object | unknown, Ty extends ValidProcType, I extends PayloadType, O extends PayloadType, E extends RiverError, Init extends PayloadType | null = null> = Ty extends 'rpc' ? Init extends null ? {
144
+ type Procedure<State, Ty extends ValidProcType, I extends PayloadType, O extends PayloadType, E extends RiverError, Init extends PayloadType | null = null> = Ty extends 'rpc' ? Init extends null ? {
144
145
  input: I;
145
146
  output: O;
146
147
  errors: E;
@@ -224,9 +225,9 @@ declare class ServiceBuilder<T extends Service<string, object, ProcListing>> {
224
225
  */
225
226
  static create<Name extends string>(name: Name): ServiceBuilder<{
226
227
  name: Name;
227
- state: {};
228
- procedures: {};
228
+ state: object;
229
+ procedures: ProcListing;
229
230
  }>;
230
231
  }
231
232
 
232
- export { AnyService as A, Err as E, Ok as O, PayloadType as P, RiverError as R, ServiceContext as S, UNCAUGHT_ERROR as U, ValidProcType as V, Procedure as a, Result as b, RiverUncaughtSchema as c, AnyProcedure as d, ProcType as e, ProcInput as f, ProcOutput as g, ProcErrors as h, ProcHasInit as i, ProcInit as j, ServiceBuilder as k, ProcListing as l, Service as m, ProcHandler as n, ServiceContextWithState as o, RiverErrorSchema as p, serializeService as s };
233
+ export { AnyService as A, Err as E, Ok as O, PayloadType as P, RiverError as R, ServiceContext as S, UNCAUGHT_ERROR as U, ValidProcType as V, Procedure as a, Result as b, RiverUncaughtSchema as c, ProcType as d, ProcInput as e, ProcOutput as f, ProcErrors as g, ProcHasInit as h, ProcInit as i, ServiceBuilder as j, ProcListing as k, Service as l, ProcHandler as m, ServiceContextWithState as n, RiverErrorSchema as o, serializeService as s };