mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
Merge branch 'feature/grpc-server-package-definition' of https://github.com/krugi/nest into krugi-feature/grpc-server-package-definition
This commit is contained in:
@@ -10,6 +10,7 @@ import { ClientGrpc, GrpcOptions } from '../interfaces';
|
||||
import { ClientProxy } from './client-proxy';
|
||||
import { GRPC_CANCELLED } from './constants';
|
||||
import { ChannelOptions } from '../external/grpc-options.interface';
|
||||
import { getGrpcPackageDefinition } from '../helpers';
|
||||
|
||||
let grpcPackage: any = {};
|
||||
let grpcProtoLoaderPackage: any = {};
|
||||
@@ -300,16 +301,11 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
|
||||
|
||||
public loadProto(): any {
|
||||
try {
|
||||
const file = this.getOptionsProp(this.options, 'protoPath');
|
||||
const loader = this.getOptionsProp(this.options, 'loader');
|
||||
|
||||
const packageDefinition =
|
||||
this.getOptionsProp(this.options, 'packageDefinition') ||
|
||||
grpcProtoLoaderPackage.loadSync(file, loader);
|
||||
|
||||
const packageObject =
|
||||
grpcPackage.loadPackageDefinition(packageDefinition);
|
||||
return packageObject;
|
||||
const packageDefinition = getGrpcPackageDefinition(
|
||||
this.options,
|
||||
grpcProtoLoaderPackage,
|
||||
);
|
||||
return grpcPackage.loadPackageDefinition(packageDefinition);
|
||||
} catch (err) {
|
||||
const invalidProtoError = new InvalidProtoDefinitionException(err.path);
|
||||
const message =
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';
|
||||
|
||||
export class InvalidGrpcPackageDefinitionMissingPacakgeDefinitionException extends RuntimeException {
|
||||
constructor() {
|
||||
super('protoPath or packageDefinition must be defined');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';
|
||||
|
||||
export class InvalidGrpcPackageDefinitionMutexException extends RuntimeException {
|
||||
constructor() {
|
||||
super(
|
||||
'Both protoPath and packageDefinition were provided, but only one can be defined',
|
||||
);
|
||||
}
|
||||
}
|
||||
24
packages/microservices/helpers/grpc-helpers.ts
Normal file
24
packages/microservices/helpers/grpc-helpers.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { GrpcOptions } from '../interfaces';
|
||||
import { InvalidGrpcPackageDefinitionMutexException } from '../errors/invalid-grpc-package-definition-mutex.exception';
|
||||
import { InvalidGrpcPackageDefinitionMissingPacakgeDefinitionException } from '../errors/invalid-grpc-package-definition-missing-package-definition.exception';
|
||||
|
||||
export function getGrpcPackageDefinition(
|
||||
options: GrpcOptions['options'],
|
||||
grpcProtoLoaderPackage: any,
|
||||
) {
|
||||
const file = options['protoPath'];
|
||||
const packageDefinition = options['packageDefinition'];
|
||||
|
||||
if ([file, packageDefinition].every(x => x != undefined)) {
|
||||
throw new InvalidGrpcPackageDefinitionMutexException();
|
||||
}
|
||||
|
||||
if ([file, packageDefinition].every(x => x == undefined)) {
|
||||
throw new InvalidGrpcPackageDefinitionMissingPacakgeDefinitionException();
|
||||
}
|
||||
|
||||
return (
|
||||
packageDefinition ||
|
||||
grpcProtoLoaderPackage.loadSync(file, options['loader'])
|
||||
);
|
||||
}
|
||||
@@ -3,3 +3,4 @@ export * from './kafka-logger';
|
||||
export * from './kafka-parser';
|
||||
export * from './kafka-reply-partition-assigner';
|
||||
export * from './tcp-socket';
|
||||
export * from './grpc-helpers';
|
||||
|
||||
@@ -61,7 +61,7 @@ export interface GrpcOptions {
|
||||
};
|
||||
channelOptions?: ChannelOptions;
|
||||
credentials?: any;
|
||||
protoPath: string | string[];
|
||||
protoPath?: string | string[];
|
||||
package: string | string[];
|
||||
protoLoader?: string;
|
||||
packageDefinition?: any;
|
||||
|
||||
@@ -26,6 +26,7 @@ import { ChannelOptions } from '../external/grpc-options.interface';
|
||||
import { CustomTransportStrategy, MessageHandler } from '../interfaces';
|
||||
import { GrpcOptions } from '../interfaces/microservice-configuration.interface';
|
||||
import { Server } from './server';
|
||||
import { getGrpcPackageDefinition } from '../helpers';
|
||||
|
||||
let grpcPackage: any = {};
|
||||
let grpcProtoLoaderPackage: any = {};
|
||||
@@ -501,20 +502,18 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
|
||||
|
||||
public loadProto(): any {
|
||||
try {
|
||||
const file = this.getOptionsProp(this.options, 'protoPath');
|
||||
const loader = this.getOptionsProp(this.options, 'loader');
|
||||
|
||||
const packageDefinition = grpcProtoLoaderPackage.loadSync(file, loader);
|
||||
const packageObject =
|
||||
grpcPackage.loadPackageDefinition(packageDefinition);
|
||||
return packageObject;
|
||||
const packageDefinition = getGrpcPackageDefinition(
|
||||
this.options,
|
||||
grpcProtoLoaderPackage,
|
||||
);
|
||||
return grpcPackage.loadPackageDefinition(packageDefinition);
|
||||
} catch (err) {
|
||||
const invalidProtoError = new InvalidProtoDefinitionException(err.path);
|
||||
const message =
|
||||
err && err.message ? err.message : invalidProtoError.message;
|
||||
|
||||
this.logger.error(message, invalidProtoError.stack);
|
||||
throw err;
|
||||
throw invalidProtoError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ import { expect } from 'chai';
|
||||
import { join } from 'path';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { ClientGrpcProxy } from '../../client/client-grpc';
|
||||
import { ClientGrpcProxy } from '../../client';
|
||||
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcServiceException } from '../../errors/invalid-grpc-service.exception';
|
||||
import { InvalidProtoDefinitionException } from '../../errors/invalid-proto-definition.exception';
|
||||
import * as grpcHelpers from '../../helpers/grpc-helpers';
|
||||
|
||||
class NoopLogger extends Logger {
|
||||
log(message: any, context?: string): void {}
|
||||
@@ -443,13 +444,18 @@ describe('ClientGrpcProxy', () => {
|
||||
describe('loadProto', () => {
|
||||
describe('when proto is invalid', () => {
|
||||
it('should throw InvalidProtoDefinitionException', () => {
|
||||
sinon.stub(client, 'getOptionsProp' as any).callsFake(() => {
|
||||
const getPackageDefinitionStub = sinon.stub(
|
||||
grpcHelpers,
|
||||
'getGrpcPackageDefinition' as any,
|
||||
);
|
||||
getPackageDefinitionStub.callsFake(() => {
|
||||
throw new Error();
|
||||
});
|
||||
(client as any).logger = new NoopLogger();
|
||||
expect(() => client.loadProto()).to.throws(
|
||||
InvalidProtoDefinitionException,
|
||||
);
|
||||
getPackageDefinitionStub.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
56
packages/microservices/test/helpers/grpc-helpers.spec.ts
Normal file
56
packages/microservices/test/helpers/grpc-helpers.spec.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { expect } from 'chai';
|
||||
import { getGrpcPackageDefinition } from '../../helpers/grpc-helpers';
|
||||
import { InvalidGrpcPackageDefinitionMutexException } from '../../errors/invalid-grpc-package-definition-mutex.exception';
|
||||
import { InvalidGrpcPackageDefinitionMissingPacakgeDefinitionException } from '../../errors/invalid-grpc-package-definition-missing-package-definition.exception';
|
||||
|
||||
const grpcProtoLoaderPackage = { loadSync: (a, b) => 'withLoader' };
|
||||
|
||||
describe('getGrpcPackageDefinition', () => {
|
||||
it('missing both protoPath and packageDefinition', () => {
|
||||
expect(() =>
|
||||
getGrpcPackageDefinition(
|
||||
{
|
||||
package: 'somePackage',
|
||||
},
|
||||
grpcProtoLoaderPackage,
|
||||
),
|
||||
).to.throw(InvalidGrpcPackageDefinitionMissingPacakgeDefinitionException);
|
||||
});
|
||||
|
||||
it('got both protoPath and packageDefinition', () => {
|
||||
expect(() =>
|
||||
getGrpcPackageDefinition(
|
||||
{
|
||||
package: 'somePackage',
|
||||
protoPath: 'some/path',
|
||||
packageDefinition: {},
|
||||
},
|
||||
grpcProtoLoaderPackage,
|
||||
),
|
||||
).to.throw(InvalidGrpcPackageDefinitionMutexException);
|
||||
});
|
||||
|
||||
it('success with protoPath', () => {
|
||||
expect(() =>
|
||||
getGrpcPackageDefinition(
|
||||
{
|
||||
package: 'somePackage',
|
||||
protoPath: 'some/path',
|
||||
},
|
||||
grpcProtoLoaderPackage,
|
||||
),
|
||||
).to.not.throw(Error);
|
||||
});
|
||||
|
||||
it('success with packageDef', () => {
|
||||
expect(() =>
|
||||
getGrpcPackageDefinition(
|
||||
{
|
||||
package: 'somePackage',
|
||||
packageDefinition: {},
|
||||
},
|
||||
grpcProtoLoaderPackage,
|
||||
),
|
||||
).to.not.throw(Error);
|
||||
});
|
||||
});
|
||||
@@ -13,7 +13,9 @@ import * as sinon from 'sinon';
|
||||
import { CANCEL_EVENT } from '../../constants';
|
||||
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
|
||||
import { GrpcMethodStreamingType } from '../../index';
|
||||
import { ServerGrpc } from '../../server/server-grpc';
|
||||
import { ServerGrpc } from '../../server';
|
||||
import { InvalidProtoDefinitionException } from '../../errors/invalid-proto-definition.exception';
|
||||
import * as grpcHelpers from '../../helpers/grpc-helpers';
|
||||
|
||||
class NoopLogger extends Logger {
|
||||
log(message: any, context?: string): void {}
|
||||
@@ -777,6 +779,25 @@ describe('ServerGrpc', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadProto', () => {
|
||||
describe('when proto is invalid', () => {
|
||||
it('should throw InvalidProtoDefinitionException', () => {
|
||||
const getPackageDefinitionStub = sinon.stub(
|
||||
grpcHelpers,
|
||||
'getGrpcPackageDefinition' as any,
|
||||
);
|
||||
getPackageDefinitionStub.callsFake(() => {
|
||||
throw new Error();
|
||||
});
|
||||
(server as any).logger = new NoopLogger();
|
||||
expect(() => server.loadProto()).to.throws(
|
||||
InvalidProtoDefinitionException,
|
||||
);
|
||||
getPackageDefinitionStub.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('close', () => {
|
||||
it('should call "forceShutdown" by default', async () => {
|
||||
const grpcClient = {
|
||||
|
||||
Reference in New Issue
Block a user