-
Notifications
You must be signed in to change notification settings - Fork 132
/
reflection-info.ts
176 lines (147 loc) · 4.82 KB
/
reflection-info.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import {IMessageType, JsonValue, lowerCamelCase} from "@protobuf-ts/runtime";
/**
* Describes a protobuf service for runtime reflection.
*/
export interface ServiceInfo {
/**
* The protobuf type name of the service, including package name if
* present.
*/
readonly typeName: string;
/**
* Information for each rpc method of the service, in the order of
* declaration in the source .proto.
*/
readonly methods: MethodInfo[];
/**
* Contains custom service options from the .proto source in JSON format.
*/
readonly options: { [extensionName: string]: JsonValue };
}
/**
* Describes a protobuf service method for runtime reflection.
*/
export interface MethodInfo<I extends object = any, O extends object = any> {
/**
* The service this method belongs to.
*/
readonly service: ServiceInfo
/**
* The name of the method as declared in .proto
*/
readonly name: string;
/**
* The name of the method in the runtime.
*/
readonly localName: string;
/**
* The idempotency level as specified in .proto.
*
* For example, the following method declaration will set
* `idempotency` to 'NO_SIDE_EFFECTS'.
*
* ```proto
* rpc Foo (FooRequest) returns (FooResponse) {
* option idempotency_level = NO_SIDE_EFFECTS
* }
* ```
*
* See `google/protobuf/descriptor.proto`, `MethodOptions`.
*/
readonly idempotency: undefined | 'NO_SIDE_EFFECTS' | 'IDEMPOTENT';
/**
* Was the rpc declared with server streaming?
*
* Example declaration:
*
* ```proto
* rpc Foo (FooRequest) returns (stream FooResponse);
* ```
*/
readonly serverStreaming: boolean;
/**
* Was the rpc declared with client streaming?
*
* Example declaration:
*
* ```proto
* rpc Foo (stream FooRequest) returns (FooResponse);
* ```
*/
readonly clientStreaming: boolean;
/**
* The generated type handler for the input message.
* Provides methods to encode / decode binary or JSON format.
*/
readonly I: IMessageType<I>;
/**
* The generated type handler for the output message.
* Provides methods to encode / decode binary or JSON format.
*/
readonly O: IMessageType<O>;
/**
* Contains custom method options from the .proto source in JSON format.
*/
readonly options: { [extensionName: string]: JsonValue };
}
/**
* Version of `MethodInfo` that does not include "service", and also allows
* the following properties to be omitted:
* - "localName": can be omitted if equal to lowerCamelCase(name)
* - "serverStreaming": omitting means `false`
* - "clientStreaming": omitting means `false`
* - "options"
*/
export type PartialMethodInfo<I extends object = any, O extends object = any> =
PartialPartial<Omit<MethodInfo<I, O>, "service">, "localName" | "idempotency" | "serverStreaming" | "clientStreaming" | "options">;
// Make all properties in T optional, except those whose keys are in the union K.
type PartialPartial<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K>;
/**
* The available client styles from @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
export enum ClientStyle {
/**
* Do not emit a client for this service.
*/
NONE = 0,
/**
* Use the call implementations of @protobuf-ts/runtime-rpc.
* This is the default behaviour.
*/
CALL = 1,
/**
* Use promises as return type.
* This style can only be used for unary methods (no server or client
* streaming).
*/
PROMISE = 2,
/**
* Use Observables from the "rxjs" package for requests and responses.
*/
RX = 3
}
/**
* Turns PartialMethodInfo into MethodInfo.
*/
export function normalizeMethodInfo<I extends object = any, O extends object = any>(method: PartialMethodInfo<I, O>, service: ServiceInfo): MethodInfo<I, O> {
let m = method as any;
m.service = service;
m.localName = m.localName ?? lowerCamelCase(m.name);
// noinspection PointlessBooleanExpressionJS
m.serverStreaming = !!m.serverStreaming;
// noinspection PointlessBooleanExpressionJS
m.clientStreaming = !!m.clientStreaming;
m.options = m.options ?? {};
m.idempotency = m.idempotency ?? undefined;
return m as MethodInfo<I, O>;
}
/**
* Read custom method options from a generated service client.
*/
export function readMethodOptions<T extends object>(service: ServiceInfo, methodName: string | number, extensionName: string, extensionType: IMessageType<T>): T | undefined {
let info = service.methods.find((m, i) => m.localName === methodName || i === methodName);
return info && info.options && info.options[extensionName]
? extensionType.fromJson(info.options[extensionName])
: undefined;
}