mirror of https://github.com/grpc/grpc-node.git
Merge pull request #2711 from n0v1/feat/method-options
grpc-loader: Expose method options
This commit is contained in:
commit
567449875d
|
@ -57,6 +57,7 @@
|
|||
"@types/node": "^10.17.26",
|
||||
"@types/yargs": "^17.0.24",
|
||||
"clang-format": "^1.2.2",
|
||||
"google-proto-files": "^3.0.2",
|
||||
"gts": "^3.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.9.2",
|
||||
|
|
|
@ -115,6 +115,34 @@ export interface EnumTypeDefinition extends ProtobufTypeDefinition {
|
|||
format: 'Protocol Buffer 3 EnumDescriptorProto';
|
||||
}
|
||||
|
||||
export enum IdempotencyLevel {
|
||||
IDEMPOTENCY_UNKNOWN = 'IDEMPOTENCY_UNKNOWN',
|
||||
NO_SIDE_EFFECTS = 'NO_SIDE_EFFECTS',
|
||||
IDEMPOTENT = 'IDEMPOTENT'
|
||||
}
|
||||
|
||||
export interface NamePart {
|
||||
name_part: string;
|
||||
is_extension: boolean;
|
||||
}
|
||||
|
||||
export interface UninterpretedOption {
|
||||
name?: NamePart[];
|
||||
identifier_value?: string;
|
||||
positive_int_value?: number;
|
||||
negative_int_value?: number;
|
||||
double_value?: number;
|
||||
string_value?: string;
|
||||
aggregate_value?: string;
|
||||
}
|
||||
|
||||
export interface MethodOptions {
|
||||
deprecated: boolean;
|
||||
idempotency_level: IdempotencyLevel;
|
||||
uninterpreted_option: UninterpretedOption[];
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export interface MethodDefinition<RequestType, ResponseType, OutputRequestType=RequestType, OutputResponseType=ResponseType> {
|
||||
path: string;
|
||||
requestStream: boolean;
|
||||
|
@ -126,6 +154,7 @@ export interface MethodDefinition<RequestType, ResponseType, OutputRequestType=R
|
|||
originalName?: string;
|
||||
requestType: MessageTypeDefinition;
|
||||
responseType: MessageTypeDefinition;
|
||||
options: MethodOptions;
|
||||
}
|
||||
|
||||
export interface ServiceDefinition {
|
||||
|
@ -220,6 +249,27 @@ function createSerializer(cls: Protobuf.Type): Serialize<object> {
|
|||
};
|
||||
}
|
||||
|
||||
function mapMethodOptions(options: Partial<MethodOptions>[] | undefined): MethodOptions {
|
||||
return (options || []).reduce((obj: MethodOptions, item: Partial<MethodOptions>) => {
|
||||
for (const [key, value] of Object.entries(item)) {
|
||||
switch (key) {
|
||||
case 'uninterpreted_option' :
|
||||
obj.uninterpreted_option.push(item.uninterpreted_option as UninterpretedOption);
|
||||
break;
|
||||
default:
|
||||
obj[key] = value
|
||||
}
|
||||
}
|
||||
return obj
|
||||
},
|
||||
{
|
||||
deprecated: false,
|
||||
idempotency_level: IdempotencyLevel.IDEMPOTENCY_UNKNOWN,
|
||||
uninterpreted_option: [],
|
||||
}
|
||||
) as MethodOptions;
|
||||
}
|
||||
|
||||
function createMethodDefinition(
|
||||
method: Protobuf.Method,
|
||||
serviceName: string,
|
||||
|
@ -242,6 +292,7 @@ function createMethodDefinition(
|
|||
originalName: camelCase(method.name),
|
||||
requestType: createMessageDefinition(requestType, fileDescriptors),
|
||||
responseType: createMessageDefinition(responseType, fileDescriptors),
|
||||
options: mapMethodOptions(method.parsedOptions),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import { rpcFileDescriptorSet } from '../test_protos/rpc.desc';
|
|||
import { readFileSync } from 'fs';
|
||||
|
||||
import * as proto_loader from '../src/index';
|
||||
import { dirname } from 'path';
|
||||
|
||||
// Relative path from build output directory to test_protos directory
|
||||
const TEST_PROTO_DIR = `${__dirname}/../../test_protos/`;
|
||||
|
@ -128,4 +129,53 @@ describe('Descriptor types', () => {
|
|||
// This will throw if the file descriptor object cannot be parsed
|
||||
proto_loader.loadFileDescriptorSetFromObject(rpcFileDescriptorSet);
|
||||
});
|
||||
|
||||
it('Can parse method options into object correctly', () => {
|
||||
const includeDirs = [
|
||||
dirname(require.resolve('google-proto-files/package.json'))
|
||||
];
|
||||
const packageDefinition = proto_loader.loadSync(`${TEST_PROTO_DIR}/method_options.proto`, { includeDirs });
|
||||
assert('Hello' in packageDefinition);
|
||||
const service = packageDefinition.Hello as proto_loader.ServiceDefinition
|
||||
assert.deepStrictEqual(service.Hello.options, {
|
||||
deprecated: true,
|
||||
idempotency_level: 'NO_SIDE_EFFECTS',
|
||||
uninterpreted_option: [{
|
||||
name: {
|
||||
name_part: 'foo',
|
||||
is_extension: false,
|
||||
},
|
||||
identifier_value: 'bar',
|
||||
positive_int_value: 9007199254740991,
|
||||
negative_int_value: -9007199254740991,
|
||||
double_value: 1.2345,
|
||||
string_value: 'foobar',
|
||||
aggregate_value: 'foobar'
|
||||
}],
|
||||
'(google.api.http)': {
|
||||
post: '/hello',
|
||||
body: '*',
|
||||
response_body: '*',
|
||||
additional_bindings: {}
|
||||
},
|
||||
'(google.api.method_signature)': 'bar'
|
||||
})
|
||||
assert.deepStrictEqual(service.HelloWithoutOptions.options, {
|
||||
deprecated: false,
|
||||
idempotency_level: 'IDEMPOTENCY_UNKNOWN',
|
||||
uninterpreted_option: []
|
||||
})
|
||||
assert.deepStrictEqual(service.HelloWithSomeOptions.options, {
|
||||
deprecated: true,
|
||||
idempotency_level: 'IDEMPOTENCY_UNKNOWN',
|
||||
uninterpreted_option: [],
|
||||
'(google.api.http)': {
|
||||
get: '/hello',
|
||||
additional_bindings: {
|
||||
body: '*',
|
||||
get: '/hello-world'
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
});
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "google/api/annotations.proto";
|
||||
import "google/api/client.proto";
|
||||
import "google/api/httpbody.proto";
|
||||
|
||||
message Empty {}
|
||||
|
||||
message MethodSignature {
|
||||
repeated string method_signature = 1;
|
||||
}
|
||||
|
||||
service Hello {
|
||||
rpc Hello (Empty) returns (Empty) {
|
||||
option deprecated = true;
|
||||
option idempotency_level = NO_SIDE_EFFECTS;
|
||||
option uninterpreted_option = {
|
||||
name: {
|
||||
name_part: 'foo'
|
||||
is_extension: false
|
||||
}
|
||||
identifier_value: 'bar'
|
||||
positive_int_value: 9007199254740991
|
||||
negative_int_value: -9007199254740991
|
||||
double_value: 1.2345
|
||||
string_value: 'foobar'
|
||||
aggregate_value: 'foobar'
|
||||
};
|
||||
option (google.api.http) = {
|
||||
post: "/hello"
|
||||
body: "*"
|
||||
response_body: "*"
|
||||
additional_bindings: {}
|
||||
};
|
||||
option (google.api.method_signature) = 'bar';
|
||||
}
|
||||
rpc HelloWithoutOptions (Empty) returns (Empty) {}
|
||||
rpc HelloWithSomeOptions (Empty) returns (Empty) {
|
||||
option deprecated = true;
|
||||
option (google.api.http) = {
|
||||
get: "/hello"
|
||||
additional_bindings: {
|
||||
get: "/hello-world"
|
||||
body: "*"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue