Skip to content

Commit 8a47045

Browse files
itaylorkentonv
andauthored
Export the Serializable type from the package. (#78)
* Changes the name of the type `Serializable` to the more correct `RpcCompatible` and exports it. This is needed to aide integration with other libraries. For instance, if you want to make a generic function that will make use of an RpcStub, you will need to declare a constraint of `RpcCompatible<T>`, but you currently can't because RpcCompatible isn't exported. The woraround is to copy the entire type definition and declare it locally, which works, but this is much simpler. * Add changeset for `RpcCompatible<T>`. --------- Co-authored-by: Kenton Varda <[email protected]>
1 parent 85fde1b commit 8a47045

File tree

3 files changed

+27
-22
lines changed

3 files changed

+27
-22
lines changed

.changeset/dirty-bikes-glow.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"capnweb": minor
3+
---
4+
5+
The package now exports the type `RpcCompatible<T>` (previously called `Serializable<T>`, but not exported), which is needed when writing generic functions on `RpcStub` / `RpcPromise`.

src/index.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import { RpcTarget as RpcTargetImpl, RpcStub as RpcStubImpl, RpcPromise as RpcPromiseImpl } from "./core.js";
66
import { serialize, deserialize } from "./serialize.js";
77
import { RpcTransport, RpcSession as RpcSessionImpl, RpcSessionOptions } from "./rpc.js";
8-
import { RpcTargetBranded, Serializable, Stub, Stubify, __RPC_TARGET_BRAND } from "./types.js";
8+
import { RpcTargetBranded, RpcCompatible, Stub, Stubify, __RPC_TARGET_BRAND } from "./types.js";
99
import { newWebSocketRpcSession as newWebSocketRpcSessionImpl,
1010
newWorkersWebSocketRpcResponse } from "./websocket.js";
1111
import { newHttpBatchRpcSession as newHttpBatchRpcSessionImpl,
@@ -18,7 +18,7 @@ forceInitMap();
1818
// Re-export public API types.
1919
export { serialize, deserialize, newWorkersWebSocketRpcResponse, newHttpBatchRpcResponse,
2020
nodeHttpBatchRpcResponse };
21-
export type { RpcTransport, RpcSessionOptions };
21+
export type { RpcTransport, RpcSessionOptions, RpcCompatible };
2222

2323
// Hack the type system to make RpcStub's types work nicely!
2424
/**
@@ -31,9 +31,9 @@ export type { RpcTransport, RpcSessionOptions };
3131
* such method exists on the remote object, an exception is thrown back. But the client does not
3232
* actually know, until that point, what methods exist.
3333
*/
34-
export type RpcStub<T extends Serializable<T>> = Stub<T>;
34+
export type RpcStub<T extends RpcCompatible<T>> = Stub<T>;
3535
export const RpcStub: {
36-
new <T extends Serializable<T>>(value: T): RpcStub<T>;
36+
new <T extends RpcCompatible<T>>(value: T): RpcStub<T>;
3737
} = <any>RpcStubImpl;
3838

3939
/**
@@ -54,7 +54,7 @@ export const RpcStub: {
5454
* if you only intend to use the promise for pipelining and you never await it, then there's no
5555
* need to transmit the resolution!
5656
*/
57-
export type RpcPromise<T extends Serializable<T>> = Stub<T> & Promise<Stubify<T>>;
57+
export type RpcPromise<T extends RpcCompatible<T>> = Stub<T> & Promise<Stubify<T>>;
5858
export const RpcPromise: {
5959
// Note: Cannot construct directly!
6060
} = <any>RpcPromiseImpl;
@@ -64,7 +64,7 @@ export const RpcPromise: {
6464
*
6565
* Most people won't use this. You only need it if you've implemented your own `RpcTransport`.
6666
*/
67-
export interface RpcSession<T extends Serializable<T> = undefined> {
67+
export interface RpcSession<T extends RpcCompatible<T> = undefined> {
6868
getRemoteMain(): RpcStub<T>;
6969
getStats(): {imports: number, exports: number};
7070

@@ -73,7 +73,7 @@ export interface RpcSession<T extends Serializable<T> = undefined> {
7373
drain(): Promise<void>;
7474
}
7575
export const RpcSession: {
76-
new <T extends Serializable<T> = undefined>(
76+
new <T extends RpcCompatible<T> = undefined>(
7777
transport: RpcTransport, localMain?: any, options?: RpcSessionOptions): RpcSession<T>;
7878
} = <any>RpcSessionImpl;
7979

@@ -106,7 +106,7 @@ interface Empty {}
106106
* @param localMain The main RPC interface to expose to the peer. Returns a stub for the main
107107
* interface exposed from the peer.
108108
*/
109-
export let newWebSocketRpcSession:<T extends Serializable<T> = Empty>
109+
export let newWebSocketRpcSession:<T extends RpcCompatible<T> = Empty>
110110
(webSocket: WebSocket | string, localMain?: any, options?: RpcSessionOptions) => RpcStub<T> =
111111
<any>newWebSocketRpcSessionImpl;
112112

@@ -117,7 +117,7 @@ export let newWebSocketRpcSession:<T extends Serializable<T> = Empty>
117117
* value is an RpcStub. You can customize anything about the request except for the method
118118
* (it will always be set to POST) and the body (which the RPC system will fill in).
119119
*/
120-
export let newHttpBatchRpcSession:<T extends Serializable<T>>
120+
export let newHttpBatchRpcSession:<T extends RpcCompatible<T>>
121121
(urlOrRequest: string | Request, options?: RpcSessionOptions) => RpcStub<T> =
122122
<any>newHttpBatchRpcSessionImpl;
123123

@@ -126,7 +126,7 @@ export let newHttpBatchRpcSession:<T extends Serializable<T>>
126126
* between an iframe and its parent frame in a browser context. Each side should call this function
127127
* on its own end of the MessageChannel.
128128
*/
129-
export let newMessagePortRpcSession:<T extends Serializable<T> = Empty>
129+
export let newMessagePortRpcSession:<T extends RpcCompatible<T> = Empty>
130130
(port: MessagePort, localMain?: any, options?: RpcSessionOptions) => RpcStub<T> =
131131
<any>newMessagePortRpcSessionImpl;
132132

src/types.d.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,34 @@ export type Stubable = RpcTargetBranded | ((...args: any[]) => any);
2121
// The reason for using a generic type here is to build a serializable subset of structured
2222
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
2323
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
24-
export type Serializable<T> =
24+
export type RpcCompatible<T> =
2525
// Structured cloneables
2626
| BaseType
2727
// Structured cloneable composites
2828
| Map<
29-
T extends Map<infer U, unknown> ? Serializable<U> : never,
30-
T extends Map<unknown, infer U> ? Serializable<U> : never
29+
T extends Map<infer U, unknown> ? RpcCompatible<U> : never,
30+
T extends Map<unknown, infer U> ? RpcCompatible<U> : never
3131
>
32-
| Set<T extends Set<infer U> ? Serializable<U> : never>
33-
| Array<T extends Array<infer U> ? Serializable<U> : never>
34-
| ReadonlyArray<T extends ReadonlyArray<infer U> ? Serializable<U> : never>
32+
| Set<T extends Set<infer U> ? RpcCompatible<U> : never>
33+
| Array<T extends Array<infer U> ? RpcCompatible<U> : never>
34+
| ReadonlyArray<T extends ReadonlyArray<infer U> ? RpcCompatible<U> : never>
3535
| {
36-
[K in keyof T]: K extends number | string ? Serializable<T[K]> : never;
36+
[K in keyof T]: K extends number | string ? RpcCompatible<T[K]> : never;
3737
}
38-
| Promise<T extends Promise<infer U> ? Serializable<U> : never>
38+
| Promise<T extends Promise<infer U> ? RpcCompatible<U> : never>
3939
// Special types
4040
| Stub<Stubable>
4141
// Serialized as stubs, see `Stubify`
4242
| Stubable;
4343

4444
// Base type for all RPC stubs, including common memory management methods.
4545
// `T` is used as a marker type for unwrapping `Stub`s later.
46-
interface StubBase<T extends Serializable<T>> extends Disposable {
46+
interface StubBase<T extends RpcCompatible<T>> extends Disposable {
4747
[__RPC_STUB_BRAND]: T;
4848
dup(): this;
4949
onRpcBroken(callback: (error: any) => void): void;
5050
}
51-
export type Stub<T extends Serializable<T>> =
51+
export type Stub<T extends RpcCompatible<T>> =
5252
T extends object ? Provider<T> & StubBase<T> : StubBase<T>;
5353

5454
type TypedArray =
@@ -125,15 +125,15 @@ type MaybeDisposable<T> = T extends object ? Disposable : unknown;
125125

126126
// Type for method return or property on an RPC interface.
127127
// - Stubable types are replaced by stubs.
128-
// - Serializable types are passed by value, with stubable types replaced by stubs
128+
// - RpcCompatible types are passed by value, with stubable types replaced by stubs
129129
// and a top-level `Disposer`.
130130
// Everything else can't be passed over RPC.
131131
// Technically, we use custom thenables here, but they quack like `Promise`s.
132132
// Intersecting with `(Maybe)Provider` allows pipelining.
133133
// prettier-ignore
134134
type Result<R> =
135135
R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
136-
: R extends Serializable<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
136+
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
137137
: never;
138138

139139
// Type for method or property on an RPC interface.

0 commit comments

Comments
 (0)