Merge pull request #972 from murgatroid99/grpc-js_server_types_export

Improve server-related types exported by grpc-js
This commit is contained in:
Michael Lumish 2019-07-29 15:57:54 -07:00 committed by GitHub
commit 716b29f0b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 29 deletions

View File

@ -38,9 +38,10 @@ import {
Serialize, Serialize,
} from './make-client'; } from './make-client';
import { Metadata } from './metadata'; import { Metadata } from './metadata';
import { Server } from './server'; import { Server, UntypedHandleCall, UntypedServiceImplementation } from './server';
import { KeyCertPair, ServerCredentials } from './server-credentials'; import { KeyCertPair, ServerCredentials } from './server-credentials';
import { StatusBuilder } from './status-builder'; import { StatusBuilder } from './status-builder';
import { ServerUnaryCall, ServerReadableStream, ServerWritableStream, ServerDuplexStream } from './server-call';
const supportedNodeVersions = require('../../package.json').engines.node; const supportedNodeVersions = require('../../package.json').engines.node;
if (!semver.satisfies(process.version, supportedNodeVersions)) { if (!semver.satisfies(process.version, supportedNodeVersions)) {
@ -213,6 +214,12 @@ export {
CallOptions, CallOptions,
StatusObject, StatusObject,
ServiceError, ServiceError,
ServerUnaryCall,
ServerReadableStream,
ServerWritableStream,
ServerDuplexStream,
UntypedHandleCall,
UntypedServiceImplementation
}; };
/* tslint:disable:no-any */ /* tslint:disable:no-any */

View File

@ -19,12 +19,12 @@ import { EventEmitter } from 'events';
import * as http2 from 'http2'; import * as http2 from 'http2';
import { Duplex, Readable, Writable } from 'stream'; import { Duplex, Readable, Writable } from 'stream';
import { ServiceError } from './call';
import { StatusObject } from './call-stream'; import { StatusObject } from './call-stream';
import { Status } from './constants'; import { Status } from './constants';
import { Deserialize, Serialize } from './make-client'; import { Deserialize, Serialize } from './make-client';
import { Metadata } from './metadata'; import { Metadata } from './metadata';
import { StreamDecoder } from './stream-decoder'; import { StreamDecoder } from './stream-decoder';
import { ObjectReadable, ObjectWritable } from './object-stream';
interface DeadlineUnitIndexSignature { interface DeadlineUnitIndexSignature {
[name: string]: number; [name: string]: number;
@ -56,6 +56,10 @@ const defaultResponseOptions = {
waitForTrailers: true, waitForTrailers: true,
} as http2.ServerStreamResponseOptions; } as http2.ServerStreamResponseOptions;
export type ServerStatusResponse = Partial<StatusObject>;
export type ServerErrorResponse = ServerStatusResponse & Error;
export type ServerSurfaceCall = { export type ServerSurfaceCall = {
cancelled: boolean; cancelled: boolean;
getPeer(): string; getPeer(): string;
@ -68,13 +72,13 @@ export type ServerUnaryCall<RequestType, ResponseType> = ServerSurfaceCall & {
export type ServerReadableStream< export type ServerReadableStream<
RequestType, RequestType,
ResponseType ResponseType
> = ServerSurfaceCall & Readable; > = ServerSurfaceCall & ObjectReadable<RequestType>;
export type ServerWritableStream< export type ServerWritableStream<
RequestType, RequestType,
ResponseType ResponseType
> = ServerSurfaceCall & Writable & { request: RequestType | null }; > = ServerSurfaceCall & ObjectWritable<ResponseType> & { request: RequestType | null };
export type ServerDuplexStream<RequestType, ResponseType> = ServerSurfaceCall & export type ServerDuplexStream<RequestType, ResponseType> = ServerSurfaceCall &
Duplex; ObjectReadable<RequestType> & ObjectWritable<ResponseType>;
export class ServerUnaryCallImpl<RequestType, ResponseType> extends EventEmitter export class ServerUnaryCallImpl<RequestType, ResponseType> extends EventEmitter
implements ServerUnaryCall<RequestType, ResponseType> { implements ServerUnaryCall<RequestType, ResponseType> {
@ -152,7 +156,7 @@ export class ServerWritableStreamImpl<RequestType, ResponseType>
this.call.setupSurfaceCall(this); this.call.setupSurfaceCall(this);
this.on('error', err => { this.on('error', err => {
this.call.sendError(err as ServiceError); this.call.sendError(err);
this.end(); this.end();
}); });
} }
@ -223,7 +227,7 @@ export class ServerDuplexStreamImpl<RequestType, ResponseType> extends Duplex
this.call.setupReadable(this); this.call.setupReadable(this);
this.on('error', err => { this.on('error', err => {
this.call.sendError(err as ServiceError); this.call.sendError(err);
this.end(); this.end();
}); });
} }
@ -247,7 +251,7 @@ ServerDuplexStreamImpl.prototype.end = ServerWritableStreamImpl.prototype.end;
// Unary response callback signature. // Unary response callback signature.
export type sendUnaryData<ResponseType> = ( export type sendUnaryData<ResponseType> = (
error: ServiceError | null, error: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null, value: ResponseType | null,
trailer?: Metadata, trailer?: Metadata,
flags?: number flags?: number
@ -339,7 +343,7 @@ export class Http2ServerCallStream<
) { ) {
super(); super();
this.stream.once('error', (err: ServiceError) => { this.stream.once('error', (err: ServerErrorResponse) => {
err.code = Status.INTERNAL; err.code = Status.INTERNAL;
this.sendError(err); this.sendError(err);
}); });
@ -379,7 +383,7 @@ export class Http2ServerCallStream<
const match = timeoutHeader[0].toString().match(DEADLINE_REGEX); const match = timeoutHeader[0].toString().match(DEADLINE_REGEX);
if (match === null) { 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; err.code = Status.OUT_OF_RANGE;
this.sendError(err); this.sendError(err);
return; return;
@ -439,7 +443,7 @@ export class Http2ServerCallStream<
} }
async sendUnaryMessage( async sendUnaryMessage(
err: ServiceError | null, err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null, value: ResponseType | null,
metadata?: Metadata, metadata?: Metadata,
flags?: number flags?: number
@ -490,22 +494,22 @@ export class Http2ServerCallStream<
} }
} }
sendError(error: ServiceError) { sendError(error: ServerErrorResponse | ServerStatusResponse) {
const status: StatusObject = { const status: StatusObject = {
code: Status.UNKNOWN, code: Status.UNKNOWN,
details: error.hasOwnProperty('message') details: ('message' in error)
? error.message ? error.message
: 'Unknown Error', : 'Unknown Error',
metadata: error.hasOwnProperty('metadata') metadata: ('metadata' in error && error.metadata !== undefined)
? error.metadata ? error.metadata
: new 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; status.code = error.code;
if (error.hasOwnProperty('details')) { if ('details' in error && typeof error.details === 'string') {
status.details = error.details; status.details = error.details!;
} }
} }
@ -637,7 +641,7 @@ export class Http2ServerCallStream<
type UntypedServerCall = Http2ServerCallStream<any, any>; type UntypedServerCall = Http2ServerCallStream<any, any>;
function handleExpiredDeadline(call: UntypedServerCall) { 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; err.code = Status.DEADLINE_EXCEEDED;
call.sendError(err); call.sendError(err);

View File

@ -41,6 +41,8 @@ import {
ServerWritableStream, ServerWritableStream,
ServerWritableStreamImpl, ServerWritableStreamImpl,
UnaryHandler, UnaryHandler,
ServerErrorResponse,
ServerStatusResponse,
} from './server-call'; } from './server-call';
import { ServerCredentials } from './server-credentials'; import { ServerCredentials } from './server-credentials';
@ -57,9 +59,9 @@ type UntypedUnaryHandler = UnaryHandler<any, any>;
type UntypedClientStreamingHandler = ClientStreamingHandler<any, any>; type UntypedClientStreamingHandler = ClientStreamingHandler<any, any>;
type UntypedServerStreamingHandler = ServerStreamingHandler<any, any>; type UntypedServerStreamingHandler = ServerStreamingHandler<any, any>;
type UntypedBidiStreamingHandler = BidiStreamingHandler<any, any>; type UntypedBidiStreamingHandler = BidiStreamingHandler<any, any>;
type UntypedHandleCall = HandleCall<any, any>; export type UntypedHandleCall = HandleCall<any, any>;
type UntypedHandler = Handler<any, any>; type UntypedHandler = Handler<any, any>;
interface UntypedServiceImplementation { export interface UntypedServiceImplementation {
[name: string]: UntypedHandleCall; [name: string]: UntypedHandleCall;
} }
@ -100,7 +102,7 @@ export class Server {
throw new Error('Not implemented. Use addService() instead'); throw new Error('Not implemented. Use addService() instead');
} }
addService(service: ServiceDefinition, implementation: object): void { addService(service: ServiceDefinition, implementation: UntypedServiceImplementation): void {
if (this.started === true) { if (this.started === true) {
throw new Error("Can't add a service to a started server."); throw new Error("Can't add a service to a started server.");
} }
@ -120,8 +122,6 @@ export class Server {
throw new Error('Cannot add an empty service to a server'); throw new Error('Cannot add an empty service to a server');
} }
const implMap: UntypedServiceImplementation = implementation as UntypedServiceImplementation;
serviceKeys.forEach(name => { serviceKeys.forEach(name => {
const attrs = service[name]; const attrs = service[name];
let methodType: HandlerType; let methodType: HandlerType;
@ -140,11 +140,11 @@ export class Server {
} }
} }
let implFn = implMap[name]; let implFn = implementation[name];
let impl; let impl;
if (implFn === undefined && typeof attrs.originalName === 'string') { if (implFn === undefined && typeof attrs.originalName === 'string') {
implFn = implMap[attrs.originalName]; implFn = implementation[attrs.originalName];
} }
if (implFn !== undefined) { if (implFn !== undefined) {
@ -414,7 +414,7 @@ async function handleUnary<RequestType, ResponseType>(
handler.func( handler.func(
emitter, emitter,
( (
err: ServiceError | null, err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null, value: ResponseType | null,
trailer?: Metadata, trailer?: Metadata,
flags?: number flags?: number
@ -436,7 +436,7 @@ function handleClientStreaming<RequestType, ResponseType>(
); );
function respond( function respond(
err: ServiceError | null, err: ServerErrorResponse | ServerStatusResponse | null,
value: ResponseType | null, value: ResponseType | null,
trailer?: Metadata, trailer?: Metadata,
flags?: number flags?: number

View File

@ -412,13 +412,13 @@ declare module "grpc" {
* User provided method to handle server streaming methods on the server. * User provided method to handle server streaming methods on the server.
*/ */
type handleServerStreamingCall<RequestType, ResponseType> = 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 * A stream that the server can write to. Used for calls that are streaming
* from the server side. * from the server side.
*/ */
export class ServerWriteableStream<RequestType> extends Writable { export class ServerWritableStream<RequestType> extends Writable {
/** /**
* Indicates if the call has been cancelled * Indicates if the call has been cancelled
*/ */
@ -449,6 +449,10 @@ declare module "grpc" {
sendMetadata(responseMetadata: Metadata): void; 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. * User provided method to handle bidirectional streaming calls on the server.
*/ */