Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2: Replace MethodInfo with Descriptor Types #1255

Merged
merged 2 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/connect-web/src/connect-transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import type {
UnaryRequest,
UnaryResponse,
ContextValues,
MethodInfo,
DescMethodUnary,
DescMethodStreaming,
} from "@connectrpc/connect";
import {
Code,
Expand Down Expand Up @@ -140,7 +141,7 @@ export function createConnectTransport(
const useBinaryFormat = options.useBinaryFormat ?? false;
return {
async unary<I extends DescMessage, O extends DescMessage>(
method: MethodInfo<I, O>,
method: DescMethodUnary<I, O>,
signal: AbortSignal | undefined,
timeoutMs: number | undefined,
header: HeadersInit | undefined,
Expand Down Expand Up @@ -238,7 +239,7 @@ export function createConnectTransport(
},

async stream<I extends DescMessage, O extends DescMessage>(
method: MethodInfo<I, O>,
method: DescMethodStreaming<I, O>,
signal: AbortSignal | undefined,
timeoutMs: number | undefined,
header: HeadersInit | undefined,
Expand Down
7 changes: 4 additions & 3 deletions packages/connect-web/src/grpc-web-transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import type {
UnaryRequest,
UnaryResponse,
ContextValues,
MethodInfo,
DescMethodUnary,
DescMethodStreaming,
} from "@connectrpc/connect";
import { createContextValues, ConnectError, Code } from "@connectrpc/connect";
import {
Expand Down Expand Up @@ -130,7 +131,7 @@ export function createGrpcWebTransport(
const useBinaryFormat = options.useBinaryFormat ?? true;
return {
async unary<I extends DescMessage, O extends DescMessage>(
method: MethodInfo<I, O>,
method: DescMethodUnary<I, O>,
signal: AbortSignal | undefined,
timeoutMs: number | undefined,
header: Headers,
Expand Down Expand Up @@ -241,7 +242,7 @@ export function createGrpcWebTransport(
},

async stream<I extends DescMessage, O extends DescMessage>(
method: MethodInfo<I, O>,
method: DescMethodStreaming<I, O>,
signal: AbortSignal | undefined,
timeoutMs: number | undefined,
header: HeadersInit | undefined,
Expand Down
5 changes: 2 additions & 3 deletions packages/connect/src/any-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import type { DescService } from "@bufbuild/protobuf";
import type { MethodInfo } from "./types.js";
import type { DescMethod, DescService } from "@bufbuild/protobuf";

/**
* AnyClient is an arbitrary service client with any method signature.
Expand All @@ -25,7 +24,7 @@ export type AnyClient = Record<string, AnyClientMethod>;

type AnyClientMethod = (...args: any[]) => any; // eslint-disable-line @typescript-eslint/no-explicit-any

type CreateAnyClientMethod = (method: MethodInfo) => AnyClientMethod | null;
type CreateAnyClientMethod = (method: DescMethod) => AnyClientMethod | null;

/**
* Create any client for the given service.
Expand Down
37 changes: 22 additions & 15 deletions packages/connect/src/callback-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ import { Code } from "./code.js";
import { makeAnyClient } from "./any-client.js";
import type { CallOptions } from "./call-options.js";
import { createAsyncIterable } from "./protocol/async-iterable.js";
import type { MethodInfoServerStreaming, MethodInfoUnary } from "./types.js";
import type {
DescMethodServerStreaming,
DescMethodStreaming,
DescMethodUnary,
} from "./types.js";

// prettier-ignore
/**
Expand All @@ -48,8 +52,8 @@ import type { MethodInfoServerStreaming, MethodInfoUnary } from "./types.js";
export type CallbackClient<Desc extends DescService> =
{
[P in keyof Desc["method"]]:
Desc["method"][P] extends MethodInfoUnary<infer I, infer O> ? (request: MessageInitShape<I>, callback: (error: ConnectError | undefined, response: MessageShape<O>) => void, options?: CallOptions) => CancelFn
: Desc["method"][P] extends MethodInfoServerStreaming<infer I, infer O> ? (request: MessageInitShape<I>, messageCallback: (response: MessageShape<O>) => void, closeCallback: (error: ConnectError | undefined) => void, options?: CallOptions) => CancelFn
Desc["method"][P] extends DescMethodUnary<infer I, infer O> ? (request: MessageInitShape<I>, callback: (error: ConnectError | undefined, response: MessageShape<O>) => void, options?: CallOptions) => CancelFn
: Desc["method"][P] extends DescMethodServerStreaming<infer I, infer O> ? (request: MessageInitShape<I>, messageCallback: (response: MessageShape<O>) => void, closeCallback: (error: ConnectError | undefined) => void, options?: CallOptions) => CancelFn
: never;
}

Expand All @@ -63,16 +67,19 @@ export function createCallbackClient<T extends DescService>(
service: T,
transport: Transport,
) {
return makeAnyClient(service, (method) => {
switch (method.methodKind) {
case "unary":
return createUnaryFn(transport, method);
case "server_streaming":
return createServerStreamingFn(transport, method);
default:
return null;
}
}) as CallbackClient<T>;
return makeAnyClient(
service,
(method: DescMethodUnary | DescMethodStreaming) => {
switch (method.methodKind) {
case "unary":
return createUnaryFn(transport, method);
case "server_streaming":
return createServerStreamingFn(transport, method);
default:
return null;
}
},
) as CallbackClient<T>;
}

/**
Expand All @@ -89,7 +96,7 @@ type UnaryFn<I extends DescMessage, O extends DescMessage> = (

function createUnaryFn<I extends DescMessage, O extends DescMessage>(
transport: Transport,
method: MethodInfoUnary<I, O>,
method: DescMethodUnary<I, O>,
): UnaryFn<I, O> {
return function (requestMessage, callback, options) {
const abort = new AbortController();
Expand Down Expand Up @@ -135,7 +142,7 @@ type ServerStreamingFn<I extends DescMessage, O extends DescMessage> = (

function createServerStreamingFn<I extends DescMessage, O extends DescMessage>(
transport: Transport,
method: MethodInfoServerStreaming<I, O>,
method: DescMethodServerStreaming<I, O>,
): ServerStreamingFn<I, O> {
return function (input, onResponse, onClose, options) {
const abort = new AbortController();
Expand Down
41 changes: 19 additions & 22 deletions packages/connect/src/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ import {
import { createContextValues } from "./context-values.js";
import type { ContextValues } from "./context-values.js";
import type {
MethodInfoBiDiStreaming,
MethodInfoClientStreaming,
MethodInfo,
MethodInfoServerStreaming,
MethodInfoUnary,
DescMethodBiDiStreaming,
DescMethodClientStreaming,
DescMethodServerStreaming,
DescMethodStreaming,
DescMethodUnary,
} from "./types.js";

// prettier-ignore
Expand All @@ -47,11 +47,11 @@ export type ServiceImpl<Desc extends DescService> = {
/**
* MethodImpl is the signature of the implementation of an RPC.
*/
export type MethodImpl<M extends MethodInfo> =
M extends MethodInfoUnary<infer I, infer O> ? UnaryImpl<I, O>
: M extends MethodInfoServerStreaming<infer I, infer O> ? ServerStreamingImpl<I, O>
: M extends MethodInfoClientStreaming<infer I, infer O> ? ClientStreamingImpl<I, O>
: M extends MethodInfoBiDiStreaming<infer I, infer O> ? BiDiStreamingImpl<I, O>
export type MethodImpl<M extends DescMethod> =
M extends DescMethodUnary<infer I, infer O> ? UnaryImpl<I, O>
: M extends DescMethodServerStreaming<infer I, infer O> ? ServerStreamingImpl<I, O>
: M extends DescMethodClientStreaming<infer I, infer O> ? ClientStreamingImpl<I, O>
: M extends DescMethodBiDiStreaming<infer I, infer O> ? BiDiStreamingImpl<I, O>
: never;

/**
Expand Down Expand Up @@ -232,15 +232,11 @@ export type BiDiStreamingImpl<I extends DescMessage, O extends DescMessage> = (
* metadata in a discriminated union type.
*/
export type MethodImplSpec<I extends DescMessage = DescMessage, O extends DescMessage = DescMessage> =
{
method: MethodInfo<I, O>;
}
& (
| { kind: "unary"; impl: UnaryImpl<I, O> }
| { kind: "server_streaming"; impl: ServerStreamingImpl<I, O> }
| { kind: "client_streaming"; impl: ClientStreamingImpl<I, O> }
| { kind: "bidi_streaming"; impl: BiDiStreamingImpl<I, O> }
);
| { kind: "unary"; impl: UnaryImpl<I, O>; method: DescMethodUnary<I, O> }
| { kind: "server_streaming"; impl: ServerStreamingImpl<I, O>; method: DescMethodServerStreaming<I, O> }
| { kind: "client_streaming"; impl: ClientStreamingImpl<I, O>; method: DescMethodClientStreaming<I, O> }
| { kind: "bidi_streaming"; impl: BiDiStreamingImpl<I, O>; method: DescMethodBiDiStreaming<I, O> }
;

/**
* Wraps a user-provided service implementation and provides metadata.
Expand All @@ -256,7 +252,7 @@ export type ServiceImplSpec = {
* Create an MethodImplSpec - a user-provided implementation for a method,
* wrapped in a discriminated union type along with service and method metadata.
*/
export function createMethodImplSpec<M extends MethodInfo>(
export function createMethodImplSpec<M extends DescMethod>(
method: M,
impl: MethodImpl<M>,
): MethodImplSpec {
Expand All @@ -277,7 +273,8 @@ export function createServiceImplSpec<Desc extends DescService>(
): ServiceImplSpec {
const s: ServiceImplSpec = { service, methods: {} };
for (const method of service.methods) {
let fn: MethodImpl<MethodInfo> | undefined = impl[method.localName];
let fn: MethodImpl<DescMethodUnary | DescMethodStreaming> | undefined =
impl[method.localName];
if (typeof fn == "function") {
fn = fn.bind(impl);
} else {
Expand All @@ -287,7 +284,7 @@ export function createServiceImplSpec<Desc extends DescService>(
};
}
s.methods[method.localName] = createMethodImplSpec(
method as MethodInfo,
method as DescMethodUnary | DescMethodStreaming,
fn,
);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/connect/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,4 @@ export {
} from "./implementation.js";
export type { ServiceImplSpec, MethodImplSpec } from "./implementation.js";
export { createRouterTransport } from "./router-transport.js";

export type { MethodInfo } from "./types.js";
export type { DescMethodUnary, DescMethodStreaming } from "./types.js"; // TODO: Remove once exported from @bufbuild/protobuf
45 changes: 27 additions & 18 deletions packages/connect/src/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@

import type {
DescMessage,
DescMethod,
DescService,
MessageShape,
} from "@bufbuild/protobuf";
import type { ContextValues } from "./context-values.js";
import type { MethodInfo } from "./types.js";
import type { DescMethodStreaming, DescMethodUnary } from "./types.js";

/**
* An interceptor can add logic to clients or servers, similar to the decorators
Expand Down Expand Up @@ -67,7 +66,7 @@ type AnyFn = (
export interface UnaryRequest<
I extends DescMessage = DescMessage,
O extends DescMessage = DescMessage,
> extends RequestCommon<I, O> {
> extends RequestCommon {
/**
* The `stream` property discriminates between UnaryRequest and
* StreamingRequest.
Expand All @@ -78,6 +77,11 @@ export interface UnaryRequest<
* The input message that will be transmitted.
*/
readonly message: MessageShape<I>;

/**
* Metadata related to the service method that is being called.
*/
readonly method: DescMethodUnary<I, O>;
}

/**
Expand All @@ -87,7 +91,7 @@ export interface UnaryRequest<
export interface UnaryResponse<
I extends DescMessage = DescMessage,
O extends DescMessage = DescMessage,
> extends ResponseCommon<I, O> {
> extends ResponseCommon {
/**
* The `stream` property discriminates between UnaryResponse and
* StreamingConn.
Expand All @@ -98,6 +102,11 @@ export interface UnaryResponse<
* The received output message.
*/
readonly message: MessageShape<O>;

/**
* Metadata related to the service method that is being called.
*/
readonly method: DescMethodUnary<I, O>;
}

/**
Expand All @@ -107,7 +116,7 @@ export interface UnaryResponse<
export interface StreamRequest<
I extends DescMessage = DescMessage,
O extends DescMessage = DescMessage,
> extends RequestCommon<I, O> {
> extends RequestCommon {
/**
* The `stream` property discriminates between UnaryRequest and
* StreamingRequest.
Expand All @@ -118,6 +127,11 @@ export interface StreamRequest<
* The input messages that will be transmitted.
*/
readonly message: AsyncIterable<MessageShape<I>>;

/**
* Metadata related to the service method that is being called.
*/
readonly method: DescMethodStreaming<I, O>;
}

/**
Expand All @@ -127,7 +141,7 @@ export interface StreamRequest<
export interface StreamResponse<
I extends DescMessage = DescMessage,
O extends DescMessage = DescMessage,
> extends ResponseCommon<I, O> {
> extends ResponseCommon {
/**
* The `stream` property discriminates between UnaryResponse and
* StreamingConn.
Expand All @@ -138,12 +152,17 @@ export interface StreamResponse<
* The output messages.
*/
readonly message: AsyncIterable<MessageShape<O>>;

/**
* Metadata related to the service method that is being called.
*/
readonly method: DescMethodStreaming<I, O>;
}

/**
* @private
*/
export interface RequestCommon<I extends DescMessage, O extends DescMessage> {
export interface RequestCommon {
/**
* Metadata related to the service that is being called.
*/
Expand All @@ -155,11 +174,6 @@ export interface RequestCommon<I extends DescMessage, O extends DescMessage> {
*/
readonly requestMethod: string;

/**
* Metadata related to the service method that is being called.
*/
readonly method: MethodInfo<I, O>;

/**
* The URL the request is going to hit for the clients or the
* URL received by the server.
Expand All @@ -185,17 +199,12 @@ export interface RequestCommon<I extends DescMessage, O extends DescMessage> {
/**
* @private
*/
export interface ResponseCommon<I extends DescMessage, O extends DescMessage> {
export interface ResponseCommon {
/**
* Metadata related to the service that is being called.
*/
readonly service: DescService;

/**
* Metadata related to the service method that is being called.
*/
readonly method: DescMethod & { readonly input: I; readonly output: O };

/**
* Headers received from the response.
*/
Expand Down
Loading
Loading