Skip to content

Commit

Permalink
Merge pull request #972 from murgatroid99/grpc-js_server_types_export
Browse files Browse the repository at this point in the history
Improve server-related types exported by grpc-js
  • Loading branch information
murgatroid99 committed Jul 29, 2019
2 parents c106315 + 80d7057 commit 716b29f
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 29 deletions.
9 changes: 8 additions & 1 deletion packages/grpc-js/src/index.ts
Expand Up @@ -38,9 +38,10 @@ import {
Serialize,
} from './make-client';
import { Metadata } from './metadata';
import { Server } from './server';
import { Server, UntypedHandleCall, UntypedServiceImplementation } from './server';
import { KeyCertPair, ServerCredentials } from './server-credentials';
import { StatusBuilder } from './status-builder';
import { ServerUnaryCall, ServerReadableStream, ServerWritableStream, ServerDuplexStream } from './server-call';

const supportedNodeVersions = require('../../package.json').engines.node;
if (!semver.satisfies(process.version, supportedNodeVersions)) {
Expand Down Expand Up @@ -213,6 +214,12 @@ export {
CallOptions,
StatusObject,
ServiceError,
ServerUnaryCall,
ServerReadableStream,
ServerWritableStream,
ServerDuplexStream,
UntypedHandleCall,
UntypedServiceImplementation
};

/* tslint:disable:no-any */
Expand Down
38 changes: 21 additions & 17 deletions packages/grpc-js/src/server-call.ts
Expand Up @@ -19,12 +19,12 @@ import { EventEmitter } from 'events';
import * as http2 from 'http2';
import { Duplex, Readable, Writable } from 'stream';

import { ServiceError } from './call';
import { StatusObject } from './call-stream';
import { Status } from './constants';
import { Deserialize, Serialize } from './make-client';
import { Metadata } from './metadata';
import { StreamDecoder } from './stream-decoder';
import { ObjectReadable, ObjectWritable } from './object-stream';

interface DeadlineUnitIndexSignature {
[name: string]: number;
Expand Down Expand Up @@ -56,6 +56,10 @@ const defaultResponseOptions = {
waitForTrailers: true,
} as http2.ServerStreamResponseOptions;

export type ServerStatusResponse = Partial<StatusObject>;

export type ServerErrorResponse = ServerStatusResponse & Error;

export type ServerSurfaceCall = {
cancelled: boolean;
getPeer(): string;
Expand All @@ -68,13 +72,13 @@ export type ServerUnaryCall<RequestType, ResponseType> = ServerSurfaceCall & {
export type ServerReadableStream<
RequestType,
ResponseType
> = ServerSurfaceCall & Readable;
> = ServerSurfaceCall & ObjectReadable<RequestType>;
export type ServerWritableStream<
RequestType,
ResponseType
> = ServerSurfaceCall & Writable & { request: RequestType | null };
> = ServerSurfaceCall & ObjectWritable<ResponseType> & { request: RequestType | null };
export type ServerDuplexStream<RequestType, ResponseType> = ServerSurfaceCall &
Duplex;
ObjectReadable<RequestType> & ObjectWritable<ResponseType>;

export class ServerUnaryCallImpl<RequestType, ResponseType> extends EventEmitter
implements ServerUnaryCall<RequestType, ResponseType> {
Expand Down Expand Up @@ -152,7 +156,7 @@ export class ServerWritableStreamImpl<RequestType, ResponseType>
this.call.setupSurfaceCall(this);

this.on('error', err => {
this.call.sendError(err as ServiceError);
this.call.sendError(err);
this.end();
});
}
Expand Down Expand Up @@ -223,7 +227,7 @@ export class ServerDuplexStreamImpl<RequestType, ResponseType> extends Duplex
this.call.setupReadable(this);

this.on('error', err => {
this.call.sendError(err as ServiceError);
this.call.sendError(err);
this.end();
});
}
Expand All @@ -247,7 +251,7 @@ ServerDuplexStreamImpl.prototype.end = ServerWritableStreamImpl.prototype.end;

// Unary response callback signature.
export type sendUnaryData<ResponseType> = (
error: ServiceError | null,
error: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null,
trailer?: Metadata,
flags?: number
Expand Down Expand Up @@ -339,7 +343,7 @@ export class Http2ServerCallStream<
) {
super();

this.stream.once('error', (err: ServiceError) => {
this.stream.once('error', (err: ServerErrorResponse) => {
err.code = Status.INTERNAL;
this.sendError(err);
});
Expand Down Expand Up @@ -379,7 +383,7 @@ export class Http2ServerCallStream<
const match = timeoutHeader[0].toString().match(DEADLINE_REGEX);

if (match === null) {
const err = new Error('Invalid deadline') as ServiceError;
const err = new Error('Invalid deadline') as ServerErrorResponse;
err.code = Status.OUT_OF_RANGE;
this.sendError(err);
return;
Expand Down Expand Up @@ -439,7 +443,7 @@ export class Http2ServerCallStream<
}

async sendUnaryMessage(
err: ServiceError | null,
err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null,
metadata?: Metadata,
flags?: number
Expand Down Expand Up @@ -490,22 +494,22 @@ export class Http2ServerCallStream<
}
}

sendError(error: ServiceError) {
sendError(error: ServerErrorResponse | ServerStatusResponse) {
const status: StatusObject = {
code: Status.UNKNOWN,
details: error.hasOwnProperty('message')
details: ('message' in error)
? error.message
: 'Unknown Error',
metadata: error.hasOwnProperty('metadata')
metadata: ('metadata' in error && error.metadata !== undefined)
? error.metadata
: new Metadata(),
};

if (error.hasOwnProperty('code') && Number.isInteger(error.code)) {
if ('code' in error && typeof error.code === 'number' && Number.isInteger(error.code)) {
status.code = error.code;

if (error.hasOwnProperty('details')) {
status.details = error.details;
if ('details' in error && typeof error.details === 'string') {
status.details = error.details!;
}
}

Expand Down Expand Up @@ -637,7 +641,7 @@ export class Http2ServerCallStream<
type UntypedServerCall = Http2ServerCallStream<any, any>;

function handleExpiredDeadline(call: UntypedServerCall) {
const err = new Error('Deadline exceeded') as ServiceError;
const err = new Error('Deadline exceeded') as ServerErrorResponse;
err.code = Status.DEADLINE_EXCEEDED;

call.sendError(err);
Expand Down
18 changes: 9 additions & 9 deletions packages/grpc-js/src/server.ts
Expand Up @@ -41,6 +41,8 @@ import {
ServerWritableStream,
ServerWritableStreamImpl,
UnaryHandler,
ServerErrorResponse,
ServerStatusResponse,
} from './server-call';
import { ServerCredentials } from './server-credentials';

Expand All @@ -57,9 +59,9 @@ type UntypedUnaryHandler = UnaryHandler<any, any>;
type UntypedClientStreamingHandler = ClientStreamingHandler<any, any>;
type UntypedServerStreamingHandler = ServerStreamingHandler<any, any>;
type UntypedBidiStreamingHandler = BidiStreamingHandler<any, any>;
type UntypedHandleCall = HandleCall<any, any>;
export type UntypedHandleCall = HandleCall<any, any>;
type UntypedHandler = Handler<any, any>;
interface UntypedServiceImplementation {
export interface UntypedServiceImplementation {
[name: string]: UntypedHandleCall;
}

Expand Down Expand Up @@ -100,7 +102,7 @@ export class Server {
throw new Error('Not implemented. Use addService() instead');
}

addService(service: ServiceDefinition, implementation: object): void {
addService(service: ServiceDefinition, implementation: UntypedServiceImplementation): void {
if (this.started === true) {
throw new Error("Can't add a service to a started server.");
}
Expand All @@ -120,8 +122,6 @@ export class Server {
throw new Error('Cannot add an empty service to a server');
}

const implMap: UntypedServiceImplementation = implementation as UntypedServiceImplementation;

serviceKeys.forEach(name => {
const attrs = service[name];
let methodType: HandlerType;
Expand All @@ -140,11 +140,11 @@ export class Server {
}
}

let implFn = implMap[name];
let implFn = implementation[name];
let impl;

if (implFn === undefined && typeof attrs.originalName === 'string') {
implFn = implMap[attrs.originalName];
implFn = implementation[attrs.originalName];
}

if (implFn !== undefined) {
Expand Down Expand Up @@ -414,7 +414,7 @@ async function handleUnary<RequestType, ResponseType>(
handler.func(
emitter,
(
err: ServiceError | null,
err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null,
trailer?: Metadata,
flags?: number
Expand All @@ -436,7 +436,7 @@ function handleClientStreaming<RequestType, ResponseType>(
);

function respond(
err: ServiceError | null,
err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null,
trailer?: Metadata,
flags?: number
Expand Down
8 changes: 6 additions & 2 deletions packages/grpc-native-core/index.d.ts
Expand Up @@ -412,13 +412,13 @@ declare module "grpc" {
* User provided method to handle server streaming methods on the server.
*/
type handleServerStreamingCall<RequestType, ResponseType> =
(call: ServerWriteableStream<RequestType>) => void;
(call: ServerWritableStream<RequestType>) => void;

/**
* A stream that the server can write to. Used for calls that are streaming
* from the server side.
*/
export class ServerWriteableStream<RequestType> extends Writable {
export class ServerWritableStream<RequestType> extends Writable {
/**
* Indicates if the call has been cancelled
*/
Expand Down Expand Up @@ -449,6 +449,10 @@ declare module "grpc" {
sendMetadata(responseMetadata: Metadata): void;
}

/* This typo existed in previous versions of this file, so we provide this
* type alias for backwards compatibility. */
export type ServerWriteableStream<RequestType> = ServerWritableStream<RequestType>;

/**
* User provided method to handle bidirectional streaming calls on the server.
*/
Expand Down

0 comments on commit 716b29f

Please sign in to comment.