@replit/river 0.1.6 → 0.1.7

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.
@@ -27,6 +27,7 @@ export declare const TestServiceConstructor: () => {
27
27
  }>>;
28
28
  type: "rpc";
29
29
  };
30
+ } & {
30
31
  echo: {
31
32
  input: import("@sinclair/typebox").TObject<{
32
33
  msg: import("@sinclair/typebox").TString;
@@ -0,0 +1,7 @@
1
+ import { MessageId, OpaqueTransportMessage } from '../transport/message';
2
+ import { Transport } from '../transport/types';
3
+ export declare class MockTransport extends Transport {
4
+ constructor(clientId: string);
5
+ send(msg: OpaqueTransportMessage): MessageId;
6
+ close(): Promise<void>;
7
+ }
@@ -0,0 +1,97 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { ServiceBuilder, serializeService } from '../router/builder';
3
+ import { Type } from '@sinclair/typebox';
4
+ import { reply } from '../transport/message';
5
+ import { createServer } from '../router/server';
6
+ import { Transport } from '../transport/types';
7
+ import { NaiveJsonCodec } from '../codec/json';
8
+ import { createClient } from '../router/client';
9
+ const fnBody = {
10
+ type: 'rpc',
11
+ input: Type.Object({ a: Type.Number() }),
12
+ output: Type.Object({ b: Type.Number() }),
13
+ async handler(_state, msg) {
14
+ return reply(msg, { b: msg.payload.a });
15
+ },
16
+ };
17
+ // typescript is limited to max 50 constraints
18
+ // see: https://github.com/microsoft/TypeScript/issues/33541
19
+ const svc = () => ServiceBuilder.create('test')
20
+ .defineProcedure('f1', fnBody)
21
+ .defineProcedure('f2', fnBody)
22
+ .defineProcedure('f3', fnBody)
23
+ .defineProcedure('f4', fnBody)
24
+ .defineProcedure('f5', fnBody)
25
+ .defineProcedure('f6', fnBody)
26
+ .defineProcedure('f7', fnBody)
27
+ .defineProcedure('f8', fnBody)
28
+ .defineProcedure('f9', fnBody)
29
+ .defineProcedure('f10', fnBody)
30
+ .defineProcedure('f11', fnBody)
31
+ .defineProcedure('f12', fnBody)
32
+ .defineProcedure('f13', fnBody)
33
+ .defineProcedure('f14', fnBody)
34
+ .defineProcedure('f15', fnBody)
35
+ .defineProcedure('f16', fnBody)
36
+ .defineProcedure('f17', fnBody)
37
+ .defineProcedure('f18', fnBody)
38
+ .defineProcedure('f19', fnBody)
39
+ .defineProcedure('f20', fnBody)
40
+ .defineProcedure('f21', fnBody)
41
+ .defineProcedure('f22', fnBody)
42
+ .defineProcedure('f23', fnBody)
43
+ .defineProcedure('f24', fnBody)
44
+ .defineProcedure('f25', fnBody)
45
+ .defineProcedure('f26', fnBody)
46
+ .defineProcedure('f27', fnBody)
47
+ .defineProcedure('f28', fnBody)
48
+ .defineProcedure('f29', fnBody)
49
+ .defineProcedure('f30', fnBody)
50
+ .defineProcedure('f31', fnBody)
51
+ .defineProcedure('f32', fnBody)
52
+ .defineProcedure('f33', fnBody)
53
+ .defineProcedure('f34', fnBody)
54
+ .defineProcedure('f35', fnBody)
55
+ .defineProcedure('f36', fnBody)
56
+ .defineProcedure('f37', fnBody)
57
+ .defineProcedure('f38', fnBody)
58
+ .defineProcedure('f39', fnBody)
59
+ .defineProcedure('f40', fnBody)
60
+ .defineProcedure('f41', fnBody)
61
+ .defineProcedure('f42', fnBody)
62
+ .defineProcedure('f43', fnBody)
63
+ .defineProcedure('f44', fnBody)
64
+ .defineProcedure('f45', fnBody)
65
+ .defineProcedure('f46', fnBody)
66
+ .defineProcedure('f47', fnBody)
67
+ .defineProcedure('f48', fnBody)
68
+ .defineProcedure('f49', fnBody)
69
+ .finalize();
70
+ // mock transport
71
+ export class MockTransport extends Transport {
72
+ constructor(clientId) {
73
+ super(NaiveJsonCodec, clientId);
74
+ }
75
+ send(msg) {
76
+ const id = msg.id;
77
+ return id;
78
+ }
79
+ async close() { }
80
+ }
81
+ describe("ensure typescript doesn't give up trying to infer the types for large services", () => {
82
+ test('service with many procedures hits typescript limit', () => {
83
+ expect(serializeService(svc())).toBeTruthy();
84
+ });
85
+ test('serverclient should support many services with many procedures', async () => {
86
+ const listing = {
87
+ a: svc(),
88
+ b: svc(),
89
+ c: svc(),
90
+ d: svc(),
91
+ };
92
+ const server = await createServer(new MockTransport('SERVER'), listing);
93
+ const client = createClient(new MockTransport('client'));
94
+ expect(server).toBeTruthy();
95
+ expect(client).toBeTruthy();
96
+ });
97
+ });
@@ -3,16 +3,17 @@ import type { Pushable } from 'it-pushable';
3
3
  import { TransportMessage } from '../transport/message';
4
4
  export type ValidProcType = 'stream' | 'rpc';
5
5
  export type ProcListing = Record<string, Procedure<object, ValidProcType, TObject, TObject>>;
6
- export interface Service<Name extends string = string, State extends object = object, Procs extends ProcListing = Record<string, any>> {
6
+ export interface Service<Name extends string, State extends object, Procs extends ProcListing> {
7
7
  name: Name;
8
8
  state: State;
9
9
  procedures: Procs;
10
10
  }
11
- export declare function serializeService(s: Service): object;
12
- export type ProcHandler<S extends Service, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['handler'];
13
- export type ProcInput<S extends Service, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['input'];
14
- export type ProcOutput<S extends Service, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['output'];
15
- export type ProcType<S extends Service, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['type'];
11
+ export type AnyService = Service<string, object, any>;
12
+ export declare function serializeService(s: AnyService): object;
13
+ export type ProcHandler<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['handler'];
14
+ export type ProcInput<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['input'];
15
+ export type ProcOutput<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['output'];
16
+ export type ProcType<S extends AnyService, ProcName extends keyof S['procedures']> = S['procedures'][ProcName]['type'];
16
17
  export type Procedure<State extends object | unknown, Ty extends ValidProcType, I extends TObject, O extends TObject> = Ty extends 'rpc' ? {
17
18
  input: I;
18
19
  output: O;
@@ -33,13 +34,11 @@ export declare class ServiceBuilder<T extends Service<string, object, ProcListin
33
34
  state: InitState;
34
35
  procedures: T['procedures'];
35
36
  }>;
36
- defineProcedure<ProcName extends string, Ty extends ValidProcType, I extends TObject, O extends TObject, ProcEntry = {
37
- [k in ProcName]: Procedure<T['state'], Ty, I, O>;
38
- }>(procName: ProcName, procDef: Procedure<T['state'], Ty, I, O>): ServiceBuilder<{
37
+ defineProcedure<ProcName extends string, Ty extends ValidProcType, I extends TObject, O extends TObject>(procName: ProcName, procDef: Procedure<T['state'], Ty, I, O>): ServiceBuilder<{
39
38
  name: T['name'];
40
39
  state: T['state'];
41
- procedures: {
42
- [Key in keyof (T['procedures'] & ProcEntry)]: (T['procedures'] & ProcEntry)[Key];
40
+ procedures: T['procedures'] & {
41
+ [k in ProcName]: Procedure<T['state'], Ty, I, O>;
43
42
  };
44
43
  }>;
45
44
  static create<Name extends string>(name: Name): ServiceBuilder<{
@@ -1,17 +1,17 @@
1
1
  import { Transport } from '../transport/types';
2
- import { ProcInput, ProcOutput, ProcType, Service } from './builder';
2
+ import { AnyService, ProcInput, ProcOutput, ProcType } from './builder';
3
3
  import type { Pushable } from 'it-pushable';
4
4
  import { Server } from './server';
5
5
  import { Static } from '@sinclair/typebox';
6
- type ServiceClient<Router extends Service> = {
6
+ type ServiceClient<Router extends AnyService> = {
7
7
  [ProcName in keyof Router['procedures']]: ProcType<Router, ProcName> extends 'rpc' ? (input: Static<ProcInput<Router, ProcName>>) => Promise<Static<ProcOutput<Router, ProcName>>> : () => Promise<[
8
8
  Pushable<Static<ProcInput<Router, ProcName>>>,
9
9
  AsyncIterator<Static<ProcOutput<Router, ProcName>>>,
10
10
  () => void
11
11
  ]>;
12
12
  };
13
- export type ServerClient<Srv extends Server<Record<string, Service>>> = {
13
+ export type ServerClient<Srv extends Server<Record<string, AnyService>>> = {
14
14
  [SvcName in keyof Srv['services']]: ServiceClient<Srv['services'][SvcName]>;
15
15
  };
16
- export declare const createClient: <Srv extends Server<Record<string, Service<string, object, Record<string, any>>>>>(transport: Transport) => ServerClient<Srv>;
16
+ export declare const createClient: <Srv extends Server<Record<string, AnyService>>>(transport: Transport) => ServerClient<Srv>;
17
17
  export {};
@@ -1,7 +1,7 @@
1
1
  import { Transport } from '../transport/types';
2
- import { Service } from './builder';
2
+ import { AnyService } from './builder';
3
3
  export interface Server<Services> {
4
4
  services: Services;
5
5
  close(): Promise<void>;
6
6
  }
7
- export declare function createServer<Services extends Record<string, Service>>(transport: Transport, services: Services): Promise<Server<Services>>;
7
+ export declare function createServer<Services extends Record<string, AnyService>>(transport: Transport, services: Services): Promise<Server<Services>>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@replit/river",
3
3
  "description": "It's like tRPC but... with JSON Schema Support, duplex streaming and support for service multiplexing. Transport agnostic!",
4
- "version": "0.1.6",
4
+ "version": "0.1.7",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",