@replit/river 0.9.3 → 0.10.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.
- package/dist/__tests__/bandwidth.bench.js +11 -11
- package/dist/__tests__/cleanup.test.d.ts +2 -0
- package/dist/__tests__/cleanup.test.d.ts.map +1 -0
- package/dist/__tests__/{invariants.test.js → cleanup.test.js} +47 -20
- package/dist/__tests__/disconnects.test.d.ts +2 -0
- package/dist/__tests__/disconnects.test.d.ts.map +1 -0
- package/dist/__tests__/disconnects.test.js +163 -0
- package/dist/__tests__/e2e.test.js +33 -32
- package/dist/__tests__/fixtures/cleanup.d.ts +2 -2
- package/dist/__tests__/fixtures/cleanup.d.ts.map +1 -1
- package/dist/__tests__/fixtures/cleanup.js +6 -9
- package/dist/__tests__/fixtures/services.d.ts +36 -36
- package/dist/__tests__/fixtures/services.d.ts.map +1 -1
- package/dist/__tests__/fixtures/services.js +36 -53
- package/dist/__tests__/handler.test.js +6 -7
- package/dist/__tests__/typescript-stress.test.d.ts +149 -149
- package/dist/__tests__/typescript-stress.test.d.ts.map +1 -1
- package/dist/__tests__/typescript-stress.test.js +14 -14
- package/dist/router/builder.d.ts +6 -7
- package/dist/router/builder.d.ts.map +1 -1
- package/dist/router/client.d.ts +7 -3
- package/dist/router/client.d.ts.map +1 -1
- package/dist/router/client.js +204 -106
- package/dist/router/defs.d.ts +16 -0
- package/dist/router/defs.d.ts.map +1 -0
- package/dist/router/defs.js +11 -0
- package/dist/router/index.d.ts +2 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +1 -0
- package/dist/router/result.d.ts +2 -1
- package/dist/router/result.d.ts.map +1 -1
- package/dist/router/result.js +5 -1
- package/dist/router/server.d.ts +5 -5
- package/dist/router/server.d.ts.map +1 -1
- package/dist/router/server.js +125 -82
- package/dist/transport/impls/stdio/stdio.test.js +1 -2
- package/dist/transport/impls/ws/client.d.ts +1 -4
- package/dist/transport/impls/ws/client.d.ts.map +1 -1
- package/dist/transport/impls/ws/client.js +5 -6
- package/dist/transport/impls/ws/server.d.ts +3 -0
- package/dist/transport/impls/ws/server.d.ts.map +1 -1
- package/dist/transport/impls/ws/server.js +28 -23
- package/dist/transport/impls/ws/ws.test.js +84 -16
- package/dist/transport/index.d.ts +0 -9
- package/dist/transport/index.d.ts.map +1 -1
- package/dist/transport/index.js +0 -21
- package/dist/transport/message.d.ts +3 -4
- package/dist/transport/message.d.ts.map +1 -1
- package/dist/util/testHelpers.d.ts +20 -97
- package/dist/util/testHelpers.d.ts.map +1 -1
- package/dist/util/testHelpers.js +94 -249
- package/package.json +13 -12
- package/dist/__tests__/invariants.test.d.ts +0 -2
- package/dist/__tests__/invariants.test.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript-stress.test.d.ts","sourceRoot":"","sources":["../../__tests__/typescript-stress.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"typescript-stress.test.d.ts","sourceRoot":"","sources":["../../__tests__/typescript-stress.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAuC/D,eAAO,MAAM,oBAAoB,SAAU,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDlC,CAAC;AAGhB,qBAAa,aAAc,SAAQ,SAAS,CAAC,UAAU,CAAC;gBAC1C,QAAQ,EAAE,MAAM;IAI5B,IAAI,CAAC,GAAG,EAAE,sBAAsB,GAAG,SAAS;IAK5C,8BAA8B;IACxB,mBAAmB;IACnB,KAAK;CACZ"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { describe, expect, test } from 'vitest';
|
|
2
2
|
import { ServiceBuilder, serializeService } from '../router/builder';
|
|
3
3
|
import { Type } from '@sinclair/typebox';
|
|
4
|
-
import { reply } from '../transport/message';
|
|
5
4
|
import { createServer } from '../router/server';
|
|
6
5
|
import { Transport } from '../transport/transport';
|
|
7
6
|
import { NaiveJsonCodec } from '../codec/json';
|
|
8
7
|
import { createClient } from '../router/client';
|
|
9
8
|
import { Ok } from '../router/result';
|
|
9
|
+
import { buildServiceDefs } from '../router/defs';
|
|
10
10
|
const input = Type.Union([
|
|
11
11
|
Type.Object({ a: Type.Number() }),
|
|
12
12
|
Type.Object({ c: Type.String() }),
|
|
@@ -28,17 +28,17 @@ const fnBody = {
|
|
|
28
28
|
output,
|
|
29
29
|
errors,
|
|
30
30
|
async handler(_state, msg) {
|
|
31
|
-
if ('c' in msg
|
|
32
|
-
return
|
|
31
|
+
if ('c' in msg) {
|
|
32
|
+
return Ok({ b: msg.c });
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
|
-
return
|
|
35
|
+
return Ok({ b: msg.a });
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
};
|
|
39
39
|
// typescript is limited to max 50 constraints
|
|
40
40
|
// see: https://github.com/microsoft/TypeScript/issues/33541
|
|
41
|
-
export const StupidlyLargeService = () => ServiceBuilder.create(
|
|
41
|
+
export const StupidlyLargeService = (name) => ServiceBuilder.create(name)
|
|
42
42
|
.defineProcedure('f1', fnBody)
|
|
43
43
|
.defineProcedure('f2', fnBody)
|
|
44
44
|
.defineProcedure('f3', fnBody)
|
|
@@ -104,16 +104,16 @@ export class MockTransport extends Transport {
|
|
|
104
104
|
}
|
|
105
105
|
describe("ensure typescript doesn't give up trying to infer the types for large services", () => {
|
|
106
106
|
test('service with many procedures hits typescript limit', () => {
|
|
107
|
-
expect(serializeService(StupidlyLargeService())).toBeTruthy();
|
|
107
|
+
expect(serializeService(StupidlyLargeService('test'))).toBeTruthy();
|
|
108
108
|
});
|
|
109
|
-
test('
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const server =
|
|
109
|
+
test('server client should support many services with many procedures', async () => {
|
|
110
|
+
const serviceDefs = buildServiceDefs([
|
|
111
|
+
StupidlyLargeService('a'),
|
|
112
|
+
StupidlyLargeService('b'),
|
|
113
|
+
StupidlyLargeService('c'),
|
|
114
|
+
StupidlyLargeService('d'),
|
|
115
|
+
]);
|
|
116
|
+
const server = createServer(new MockTransport('SERVER'), serviceDefs);
|
|
117
117
|
const client = createClient(new MockTransport('client'));
|
|
118
118
|
expect(client.d.f48.rpc({ a: 0 })).toBeTruthy();
|
|
119
119
|
expect(client.a.f2.rpc({ c: 'abc' })).toBeTruthy();
|
package/dist/router/builder.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { TObject, Static, TUnion } from '@sinclair/typebox';
|
|
2
2
|
import type { Pushable } from 'it-pushable';
|
|
3
|
-
import { TransportMessage } from '../transport/message';
|
|
4
3
|
import { ServiceContextWithState } from './context';
|
|
5
4
|
import { Result, RiverError, RiverUncaughtSchema } from './result';
|
|
6
5
|
/**
|
|
@@ -91,39 +90,39 @@ export type Procedure<State extends object | unknown, Ty extends ValidProcType,
|
|
|
91
90
|
input: I;
|
|
92
91
|
output: O;
|
|
93
92
|
errors: E;
|
|
94
|
-
handler: (context: ServiceContextWithState<State>, input:
|
|
93
|
+
handler: (context: ServiceContextWithState<State>, input: Static<I>) => Promise<Result<Static<O>, Static<E>>>;
|
|
95
94
|
type: Ty;
|
|
96
95
|
} : never : Ty extends 'upload' ? Init extends PayloadType ? {
|
|
97
96
|
init: Init;
|
|
98
97
|
input: I;
|
|
99
98
|
output: O;
|
|
100
99
|
errors: E;
|
|
101
|
-
handler: (context: ServiceContextWithState<State>, init:
|
|
100
|
+
handler: (context: ServiceContextWithState<State>, init: Static<Init>, input: AsyncIterableIterator<Static<I>>) => Promise<Result<Static<O>, Static<E>>>;
|
|
102
101
|
type: Ty;
|
|
103
102
|
} : {
|
|
104
103
|
input: I;
|
|
105
104
|
output: O;
|
|
106
105
|
errors: E;
|
|
107
|
-
handler: (context: ServiceContextWithState<State>, input:
|
|
106
|
+
handler: (context: ServiceContextWithState<State>, input: AsyncIterableIterator<Static<I>>) => Promise<Result<Static<O>, Static<E>>>;
|
|
108
107
|
type: Ty;
|
|
109
108
|
} : Ty extends 'subscription' ? Init extends null ? {
|
|
110
109
|
input: I;
|
|
111
110
|
output: O;
|
|
112
111
|
errors: E;
|
|
113
|
-
handler: (context: ServiceContextWithState<State>, input:
|
|
112
|
+
handler: (context: ServiceContextWithState<State>, input: Static<I>, output: Pushable<Result<Static<O>, Static<E>>>) => Promise<void>;
|
|
114
113
|
type: Ty;
|
|
115
114
|
} : never : Ty extends 'stream' ? Init extends PayloadType ? {
|
|
116
115
|
init: Init;
|
|
117
116
|
input: I;
|
|
118
117
|
output: O;
|
|
119
118
|
errors: E;
|
|
120
|
-
handler: (context: ServiceContextWithState<State>, init:
|
|
119
|
+
handler: (context: ServiceContextWithState<State>, init: Static<Init>, input: AsyncIterableIterator<Static<I>>, output: Pushable<Result<Static<O>, Static<E>>>) => Promise<void>;
|
|
121
120
|
type: Ty;
|
|
122
121
|
} : {
|
|
123
122
|
input: I;
|
|
124
123
|
output: O;
|
|
125
124
|
errors: E;
|
|
126
|
-
handler: (context: ServiceContextWithState<State>, input:
|
|
125
|
+
handler: (context: ServiceContextWithState<State>, input: AsyncIterableIterator<Static<I>>, output: Pushable<Result<Static<O>, Static<E>>>) => Promise<void>;
|
|
127
126
|
type: Ty;
|
|
128
127
|
} : never;
|
|
129
128
|
export type AnyProcedure = Procedure<object, ValidProcType, PayloadType, PayloadType, RiverError, PayloadType | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../router/builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAQ,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../router/builder.ts"],"names":[],"mappings":"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"}
|
package/dist/router/client.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ import { Server } from './server';
|
|
|
5
5
|
import { TransportClientId } from '../transport/message';
|
|
6
6
|
import { Static } from '@sinclair/typebox';
|
|
7
7
|
import { Result } from './result';
|
|
8
|
-
|
|
8
|
+
import { EventMap } from '../transport/events';
|
|
9
|
+
import { ServiceDefs } from './defs';
|
|
10
|
+
export type AsyncIter<T> = AsyncGenerator<T, T, unknown>;
|
|
9
11
|
/**
|
|
10
12
|
* A helper type to transform an actual service type into a type
|
|
11
13
|
* we can case to in the proxy.
|
|
@@ -47,7 +49,7 @@ type ServiceClient<Router extends AnyService> = {
|
|
|
47
49
|
* Defines a type that represents a client for a server with a set of services.
|
|
48
50
|
* @template Srv - The type of the server.
|
|
49
51
|
*/
|
|
50
|
-
export type ServerClient<Srv extends Server<
|
|
52
|
+
export type ServerClient<Srv extends Server<ServiceDefs>> = {
|
|
51
53
|
[SvcName in keyof Srv['services']]: ServiceClient<Srv['services'][SvcName]>;
|
|
52
54
|
};
|
|
53
55
|
/**
|
|
@@ -63,6 +65,8 @@ export type ServerClient<Srv extends Server<Record<string, AnyService>>> = {
|
|
|
63
65
|
* @param {Transport} transport - The transport to use for communication.
|
|
64
66
|
* @returns The client for the server.
|
|
65
67
|
*/
|
|
66
|
-
export declare const createClient: <Srv extends Server<
|
|
68
|
+
export declare const createClient: <Srv extends Server<ServiceDefs>>(transport: Transport<Connection>, serverId?: TransportClientId) => ServerClient<Srv>;
|
|
69
|
+
export declare const CONNECTION_GRACE_PERIOD_MS = 5000;
|
|
70
|
+
export declare function rejectAfterDisconnectGrace(from: TransportClientId, cb: () => void): (evt: EventMap['connectionStatus']) => void;
|
|
67
71
|
export {};
|
|
68
72
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../router/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACT,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAIL,iBAAiB,EAGlB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../router/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EACL,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,UAAU,EACV,QAAQ,EACT,MAAM,WAAW,CAAC;AAEnB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAIL,iBAAiB,EAGlB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAO,MAAM,EAAyB,MAAM,UAAU,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGrC,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;AAEzD;;;;GAIG;AACH,KAAK,aAAa,CAAC,MAAM,SAAS,UAAU,IAAI;KAC7C,QAAQ,IAAI,MAAM,MAAM,CAAC,YAAY,CAAC,GAAG,QAAQ,CAChD,MAAM,EACN,QAAQ,CACT,SAAS,KAAK,GACX;QACE,GAAG,EAAE,CACH,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KACvC,OAAO,CACV,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF,CAAC;KACH,GACD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,QAAQ,GAC3C,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,IAAI,GACxC;QACE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,OAAO,CAC3D;YACE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC7C,OAAO,CACL,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF;SACF,CACF,CAAC;KACH,GACD;QACE,MAAM,EAAE,MAAM,OAAO,CACnB;YACE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC7C,OAAO,CACL,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF;SACF,CACF,CAAC;KACH,GACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,QAAQ,GAC3C,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,IAAI,GACxC;QACE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,OAAO,CAC3D;YACE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC7C,SAAS,CACP,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF;YACD,MAAM,IAAI;SACX,CACF,CAAC;KACH,GACD;QACE,MAAM,EAAE,MAAM,OAAO,CACnB;YACE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC7C,SAAS,CACP,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF;YACD,MAAM,IAAI;SACX,CACF,CAAC;KACH,GACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,cAAc,GACjD;QACE,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,OAAO,CAChE;YACE,SAAS,CACP,MAAM,CACJ,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EACpC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CACrC,CACF;YACD,MAAM,IAAI;SACX,CACF,CAAC;KACH,GACD,KAAK;CACV,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,GAAG,SAAS,MAAM,CAAC,WAAW,CAAC,IAAI;KACzD,OAAO,IAAI,MAAM,GAAG,CAAC,UAAU,CAAC,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC;CAC5E,CAAC;AAgCF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,+CACZ,UAAU,UAAU,CAAC,aACtB,iBAAiB,sBA8CA,CAAC;AAE9B,eAAO,MAAM,0BAA0B,OAAQ,CAAC;AAChD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,iBAAiB,EACvB,EAAE,EAAE,MAAM,IAAI,SAGD,QAAQ,CAAC,kBAAkB,CAAC,UAU1C"}
|
package/dist/router/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pushable } from 'it-pushable';
|
|
2
2
|
import { msg, isStreamClose, closeStream, } from '../transport/message';
|
|
3
|
-
import { waitForMessage } from '../transport';
|
|
4
3
|
import { nanoid } from 'nanoid';
|
|
4
|
+
import { Err, UNEXPECTED_DISCONNECT } from './result';
|
|
5
5
|
const noop = () => { };
|
|
6
6
|
function _createRecursiveProxy(callback, path) {
|
|
7
7
|
const proxy = new Proxy(noop, {
|
|
@@ -40,120 +40,218 @@ export const createClient = (transport, serverId = 'SERVER') => _createRecursive
|
|
|
40
40
|
throw new Error('invalid river call, ensure the service and procedure you are calling exists');
|
|
41
41
|
}
|
|
42
42
|
const [input] = opts.args;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return msg.streamId === streamId;
|
|
43
|
+
if (procType === 'rpc') {
|
|
44
|
+
return handleRpc(transport, serverId, input, serviceName, procName);
|
|
46
45
|
}
|
|
47
|
-
if (procType === 'stream') {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
46
|
+
else if (procType === 'stream') {
|
|
47
|
+
return handleStream(transport, serverId, input, serviceName, procName);
|
|
48
|
+
}
|
|
49
|
+
else if (procType === 'subscribe') {
|
|
50
|
+
return handleSubscribe(transport, serverId, input, serviceName, procName);
|
|
51
|
+
}
|
|
52
|
+
else if (procType === 'upload') {
|
|
53
|
+
return handleUpload(transport, serverId, input, serviceName, procName);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw new Error(`invalid river call, unknown procedure type ${procType}`);
|
|
57
|
+
}
|
|
58
|
+
}, []);
|
|
59
|
+
export const CONNECTION_GRACE_PERIOD_MS = 5_000; // 5s
|
|
60
|
+
export function rejectAfterDisconnectGrace(from, cb) {
|
|
61
|
+
let timeout = undefined;
|
|
62
|
+
return (evt) => {
|
|
63
|
+
if (evt.status === 'connect' && evt.conn.connectedTo === from) {
|
|
64
|
+
clearTimeout(timeout);
|
|
65
|
+
timeout = undefined;
|
|
57
66
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
67
|
+
if (evt.status === 'disconnect' && evt.conn.connectedTo === from) {
|
|
68
|
+
timeout = setTimeout(cb, CONNECTION_GRACE_PERIOD_MS);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function handleRpc(transport, serverId, input, serviceName, procName) {
|
|
73
|
+
const streamId = nanoid();
|
|
74
|
+
const m = msg(transport.clientId, serverId, streamId, input, serviceName, procName);
|
|
75
|
+
// rpc is a stream open + close
|
|
76
|
+
m.controlFlags |= 2 /* ControlFlags.StreamOpenBit */ | 4 /* ControlFlags.StreamClosedBit */;
|
|
77
|
+
transport.send(m);
|
|
78
|
+
const responsePromise = new Promise((resolve) => {
|
|
79
|
+
// on disconnect, set a timer to return an error
|
|
80
|
+
// on (re)connect, clear the timer
|
|
81
|
+
const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
|
|
82
|
+
cleanup();
|
|
83
|
+
resolve(Err({
|
|
84
|
+
code: UNEXPECTED_DISCONNECT,
|
|
85
|
+
message: `${serverId} unexpectedly disconnected`,
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
88
|
+
function cleanup() {
|
|
89
|
+
transport.removeEventListener('message', onMessage);
|
|
90
|
+
transport.removeEventListener('connectionStatus', onConnectionStatus);
|
|
91
|
+
}
|
|
92
|
+
function onMessage(msg) {
|
|
93
|
+
if (msg.streamId === streamId) {
|
|
94
|
+
// cleanup and resolve as soon as we get a message
|
|
95
|
+
cleanup();
|
|
96
|
+
resolve(msg.payload);
|
|
81
97
|
}
|
|
82
|
-
|
|
83
|
-
|
|
98
|
+
}
|
|
99
|
+
transport.addEventListener('message', onMessage);
|
|
100
|
+
transport.addEventListener('connectionStatus', onConnectionStatus);
|
|
101
|
+
});
|
|
102
|
+
return responsePromise;
|
|
103
|
+
}
|
|
104
|
+
function handleStream(transport, serverId, init, serviceName, procName) {
|
|
105
|
+
const streamId = nanoid();
|
|
106
|
+
const inputStream = pushable({ objectMode: true });
|
|
107
|
+
const outputStream = pushable({ objectMode: true });
|
|
108
|
+
let firstMessage = true;
|
|
109
|
+
if (init) {
|
|
110
|
+
const m = msg(transport.clientId, serverId, streamId, init, serviceName, procName);
|
|
111
|
+
// first message needs the open bit.
|
|
112
|
+
m.controlFlags = 2 /* ControlFlags.StreamOpenBit */;
|
|
113
|
+
transport.send(m);
|
|
114
|
+
firstMessage = false;
|
|
115
|
+
}
|
|
116
|
+
// input -> transport
|
|
117
|
+
// this gets cleaned up on inputStream.end() which is called by closeHandler
|
|
118
|
+
(async () => {
|
|
119
|
+
for await (const rawIn of inputStream) {
|
|
120
|
+
const m = msg(transport.clientId, serverId, streamId, rawIn);
|
|
121
|
+
if (firstMessage) {
|
|
122
|
+
m.serviceName = serviceName;
|
|
123
|
+
m.procedureName = procName;
|
|
124
|
+
m.controlFlags |= 2 /* ControlFlags.StreamOpenBit */;
|
|
125
|
+
firstMessage = false;
|
|
84
126
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
127
|
+
transport.send(m);
|
|
128
|
+
}
|
|
129
|
+
// after ending input stream, send a close message to the server
|
|
130
|
+
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
131
|
+
})();
|
|
132
|
+
// transport -> output
|
|
133
|
+
function onMessage(msg) {
|
|
134
|
+
if (msg.streamId !== streamId) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
138
|
+
cleanup();
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
outputStream.push(msg.payload);
|
|
142
|
+
}
|
|
94
143
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
transport.send(m);
|
|
101
|
-
return waitForMessage(transport, belongsToSameStream);
|
|
144
|
+
function cleanup() {
|
|
145
|
+
inputStream.end();
|
|
146
|
+
outputStream.end();
|
|
147
|
+
transport.removeEventListener('message', onMessage);
|
|
148
|
+
transport.removeEventListener('connectionStatus', onConnectionStatus);
|
|
102
149
|
}
|
|
103
|
-
|
|
150
|
+
const closeHandler = () => {
|
|
151
|
+
cleanup();
|
|
152
|
+
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
153
|
+
};
|
|
154
|
+
// close stream after disconnect + grace period elapses
|
|
155
|
+
const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
|
|
156
|
+
outputStream.push(Err({
|
|
157
|
+
code: UNEXPECTED_DISCONNECT,
|
|
158
|
+
message: `${serverId} unexpectedly disconnected`,
|
|
159
|
+
}));
|
|
160
|
+
cleanup();
|
|
161
|
+
});
|
|
162
|
+
transport.addEventListener('message', onMessage);
|
|
163
|
+
transport.addEventListener('connectionStatus', onConnectionStatus);
|
|
164
|
+
return [inputStream, outputStream, closeHandler];
|
|
165
|
+
}
|
|
166
|
+
function handleSubscribe(transport, serverId, input, serviceName, procName) {
|
|
167
|
+
const streamId = nanoid();
|
|
168
|
+
const m = msg(transport.clientId, serverId, streamId, input, serviceName, procName);
|
|
169
|
+
m.controlFlags |= 2 /* ControlFlags.StreamOpenBit */;
|
|
170
|
+
transport.send(m);
|
|
171
|
+
// transport -> output
|
|
172
|
+
const outputStream = pushable({ objectMode: true });
|
|
173
|
+
function onMessage(msg) {
|
|
174
|
+
if (msg.streamId !== streamId) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (isStreamClose(msg.controlFlags)) {
|
|
178
|
+
cleanup();
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
outputStream.push(msg.payload);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function cleanup() {
|
|
185
|
+
outputStream.end();
|
|
186
|
+
transport.removeEventListener('message', onMessage);
|
|
187
|
+
transport.removeEventListener('connectionStatus', onConnectionStatus);
|
|
188
|
+
}
|
|
189
|
+
const closeHandler = () => {
|
|
190
|
+
cleanup();
|
|
191
|
+
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
192
|
+
};
|
|
193
|
+
// close stream after disconnect + grace period elapses
|
|
194
|
+
const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
|
|
195
|
+
outputStream.push(Err({
|
|
196
|
+
code: UNEXPECTED_DISCONNECT,
|
|
197
|
+
message: `${serverId} unexpectedly disconnected`,
|
|
198
|
+
}));
|
|
199
|
+
cleanup();
|
|
200
|
+
});
|
|
201
|
+
transport.addEventListener('message', onMessage);
|
|
202
|
+
transport.addEventListener('connectionStatus', onConnectionStatus);
|
|
203
|
+
return [outputStream, closeHandler];
|
|
204
|
+
}
|
|
205
|
+
function handleUpload(transport, serverId, input, serviceName, procName) {
|
|
206
|
+
const streamId = nanoid();
|
|
207
|
+
const inputStream = pushable({ objectMode: true });
|
|
208
|
+
let firstMessage = true;
|
|
209
|
+
if (input) {
|
|
104
210
|
const m = msg(transport.clientId, serverId, streamId, input, serviceName, procName);
|
|
105
|
-
|
|
211
|
+
// first message needs the open bit.
|
|
212
|
+
m.controlFlags = 2 /* ControlFlags.StreamOpenBit */;
|
|
106
213
|
transport.send(m);
|
|
107
|
-
|
|
108
|
-
const outputStream = pushable({ objectMode: true });
|
|
109
|
-
const listener = (msg) => {
|
|
110
|
-
if (!belongsToSameStream(msg)) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (isStreamClose(msg.controlFlags)) {
|
|
114
|
-
outputStream.end();
|
|
115
|
-
transport.removeEventListener('message', listener);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
outputStream.push(msg.payload);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
transport.addEventListener('message', listener);
|
|
122
|
-
const closeHandler = () => {
|
|
123
|
-
outputStream.end();
|
|
124
|
-
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
125
|
-
transport.removeEventListener('message', listener);
|
|
126
|
-
};
|
|
127
|
-
return [outputStream, closeHandler];
|
|
214
|
+
firstMessage = false;
|
|
128
215
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const m = msg(transport.clientId, serverId, streamId,
|
|
134
|
-
|
|
135
|
-
|
|
216
|
+
// input -> transport
|
|
217
|
+
// this gets cleaned up on inputStream.end(), which the caller should call.
|
|
218
|
+
(async () => {
|
|
219
|
+
for await (const rawIn of inputStream) {
|
|
220
|
+
const m = msg(transport.clientId, serverId, streamId, rawIn);
|
|
221
|
+
if (firstMessage) {
|
|
222
|
+
m.controlFlags |= 2 /* ControlFlags.StreamOpenBit */;
|
|
223
|
+
m.serviceName = serviceName;
|
|
224
|
+
m.procedureName = procName;
|
|
225
|
+
firstMessage = false;
|
|
226
|
+
}
|
|
136
227
|
transport.send(m);
|
|
137
|
-
firstMessage = false;
|
|
138
228
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
229
|
+
transport.send(closeStream(transport.clientId, serverId, streamId));
|
|
230
|
+
})();
|
|
231
|
+
const responsePromise = new Promise((resolve) => {
|
|
232
|
+
// on disconnect, set a timer to return an error
|
|
233
|
+
// on (re)connect, clear the timer
|
|
234
|
+
const onConnectionStatus = rejectAfterDisconnectGrace(serverId, () => {
|
|
235
|
+
cleanup();
|
|
236
|
+
resolve(Err({
|
|
237
|
+
code: UNEXPECTED_DISCONNECT,
|
|
238
|
+
message: `${serverId} unexpectedly disconnected`,
|
|
239
|
+
}));
|
|
240
|
+
});
|
|
241
|
+
function cleanup() {
|
|
242
|
+
inputStream.end();
|
|
243
|
+
transport.removeEventListener('message', onMessage);
|
|
244
|
+
transport.removeEventListener('connectionStatus', onConnectionStatus);
|
|
245
|
+
}
|
|
246
|
+
function onMessage(msg) {
|
|
247
|
+
if (msg.streamId === streamId) {
|
|
248
|
+
// cleanup and resolve as soon as we get a message
|
|
249
|
+
cleanup();
|
|
250
|
+
resolve(msg.payload);
|
|
151
251
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
}, []);
|
|
252
|
+
}
|
|
253
|
+
transport.addEventListener('message', onMessage);
|
|
254
|
+
transport.addEventListener('connectionStatus', onConnectionStatus);
|
|
255
|
+
});
|
|
256
|
+
return [inputStream, responsePromise];
|
|
257
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AnyService } from './builder';
|
|
2
|
+
/**
|
|
3
|
+
* Defines a type for a collection service definitions. Should be
|
|
4
|
+
* build with the {@link buildServiceDefs} function.
|
|
5
|
+
* @template T - An array of services.
|
|
6
|
+
*/
|
|
7
|
+
export type ServiceDefs<T extends AnyService[] = AnyService[]> = {
|
|
8
|
+
[K in T[number]['name']]: T[number];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Builds service definitions based on an array of services.
|
|
12
|
+
* @param services - The array of services.
|
|
13
|
+
* @returns The service definitions.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildServiceDefs<T extends AnyService[]>(services: T): ServiceDefs<T>;
|
|
16
|
+
//# sourceMappingURL=defs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defs.d.ts","sourceRoot":"","sources":["../../router/defs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC;;;;GAIG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,IAAI;KAC9D,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;CACpC,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EAAE,EACrD,QAAQ,EAAE,CAAC,GACV,WAAW,CAAC,CAAC,CAAC,CAKhB"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds service definitions based on an array of services.
|
|
3
|
+
* @param services - The array of services.
|
|
4
|
+
* @returns The service definitions.
|
|
5
|
+
*/
|
|
6
|
+
export function buildServiceDefs(services) {
|
|
7
|
+
return services.reduce((acc, service) => {
|
|
8
|
+
acc[service.name] = service;
|
|
9
|
+
return acc;
|
|
10
|
+
}, {});
|
|
11
|
+
}
|
package/dist/router/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { serializeService, ServiceBuilder } from './builder';
|
|
2
2
|
export type { ValidProcType, ProcListing, Service, ProcHandler, ProcInput, ProcOutput, ProcType, Procedure, PayloadType, } from './builder';
|
|
3
|
+
export { buildServiceDefs } from './defs';
|
|
4
|
+
export type { ServiceDefs } from './defs';
|
|
3
5
|
export { createClient } from './client';
|
|
4
6
|
export type { ServerClient } from './client';
|
|
5
7
|
export { createServer } from './server';
|
|
@@ -1 +1 @@
|
|
|
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
|
+
{"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,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAC1C,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"}
|
package/dist/router/index.js
CHANGED
package/dist/router/result.d.ts
CHANGED
|
@@ -9,8 +9,9 @@ export type RiverErrorSchema = TObject<{
|
|
|
9
9
|
}>;
|
|
10
10
|
export type RiverError = TUnion<RiverErrorSchema[]> | RiverErrorSchema | TNever;
|
|
11
11
|
export declare const UNCAUGHT_ERROR = "UNCAUGHT_ERROR";
|
|
12
|
+
export declare const UNEXPECTED_DISCONNECT = "UNEXPECTED_DISCONNECT";
|
|
12
13
|
export declare const RiverUncaughtSchema: TObject<{
|
|
13
|
-
code: import("@sinclair/typebox").TLiteral<"UNCAUGHT_ERROR">;
|
|
14
|
+
code: TUnion<[import("@sinclair/typebox").TLiteral<"UNCAUGHT_ERROR">, import("@sinclair/typebox").TLiteral<"UNEXPECTED_DISCONNECT">]>;
|
|
14
15
|
message: TString;
|
|
15
16
|
}>;
|
|
16
17
|
export type Result<T, E> = {
|
|
@@ -1 +1 @@
|
|
|
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;;;
|
|
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,qBAAqB,0BAA0B,CAAC;AAC7D,eAAO,MAAM,mBAAmB;;;EAM9B,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"}
|
package/dist/router/result.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { Type, } from '@sinclair/typebox';
|
|
2
2
|
export const UNCAUGHT_ERROR = 'UNCAUGHT_ERROR';
|
|
3
|
+
export const UNEXPECTED_DISCONNECT = 'UNEXPECTED_DISCONNECT';
|
|
3
4
|
export const RiverUncaughtSchema = Type.Object({
|
|
4
|
-
code: Type.
|
|
5
|
+
code: Type.Union([
|
|
6
|
+
Type.Literal(UNCAUGHT_ERROR),
|
|
7
|
+
Type.Literal(UNEXPECTED_DISCONNECT),
|
|
8
|
+
]),
|
|
5
9
|
message: Type.String(),
|
|
6
10
|
});
|
|
7
11
|
export function Ok(payload) {
|