When using dynamic code generation, we can load .proto
files using:
const packageDefinition: PackageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
includeDirs: [__dirname],
});
We can set keepCase
option to preserve field names, don't change them to camel case. And enums
option, so we can use the string represent of enums.
Now, I am using static code generation. Facing above two problems, here is a method implementation of my service:
public async getTopics(call: ServerUnaryCall<GetTopicsRequest>, callback: sendUnaryData<GetTopicsResponse>) {
const obj = call.request.toObject();
const url = `${config.CNODE_API_URL}/topics`;
const params = {
page: obj.page || obj.page + 1,
tab: (getEnumKeyByEnumValue(Tab, obj.tab) || '').toLowerCase(),
mdrender: (getEnumKeyByEnumValue(Mdrender, obj.mdrender) || 'true').toLowerCase(),
limit: obj.limit,
};
try {
const res = await axios.get(url, { params });
const data = res.data;
// console.log(data);
const topicsResponse = new GetTopicsResponse();
data.data.forEach((po, i) => {
const topic = new Topic();
topic.setId(po.id);
topic.setAuthorId(po.author_id);
topic.setTab(Tab[po.tab.toUpperCase() as keyof typeof Tab]);
topic.setContent(po.content);
topic.setTitle(po.title);
topic.setLastReplyAt(po.last_reply_at);
topic.setGood(po.good);
topic.setTop(po.top);
topic.setReplyCount(po.reply_count);
topic.setVisitCount(po.visit_count);
topic.setCreateAt(po.create_at);
const author = new UserBase();
author.setLoginname(po.author.loginname);
author.setAvatarUrl(po.avatar_url);
topic.setAuthor(author);
topicsResponse.addData(topic, i);
});
topicsResponse.setSuccess(data.success);
callback(null, topicsResponse);
} catch (error) {
console.log(error);
const metadata = new Metadata({ idempotentRequest: true });
metadata.set('params', JSON.stringify(params));
metadata.set('url', url);
const ErrGetTopics: ServiceError = { code: status.INTERNAL, name: 'getTopicsError', message: 'call CNode API failed', metadata };
callback(ErrGetTopics, null);
}
}
Here are the problems I am facing:
- Can't set default value when using proto3, want to set default value of
page
argument to1
, NOT0
. - I need to convert enum from number to string represent manually.
- The fields from RESTful API response is snake case, but
protoc
,grpc_tools_node_protoc
andgrpc_tools_node_protoc_ts
plugin generate models which have camel case fields. So I want to keep case. - As you can see, the hydration process is not convenient and boring. I need to call setters to set value for field one by one.