Skip to content

Commit

Permalink
fix: mapping proto types to TypeScript types (#163)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-fenster committed Dec 5, 2019
1 parent 0dda49a commit 54b7ca8
Show file tree
Hide file tree
Showing 8 changed files with 554 additions and 521 deletions.
71 changes: 48 additions & 23 deletions templates/typescript_gapic/_util.njk
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,12 @@ limitations under the License.
* @param { {{- convertParamType(oneComment.paramType) -}} } {{ printRequestField(oneComment) }}
{%- endif -%}
{%- set lines = oneComment.comments -%}
{%- for line in lines %}
* {{ line.replaceAll('*/', '* /') | safe}}
{%- for line in lines %}
{%- if line.length > 0 %}
* {{ line.replaceAll('*/', '* /') | safe}}
{%- else %}
*
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{%- endif %}
Expand Down Expand Up @@ -109,42 +113,41 @@ limitations under the License.

{%- macro printReturnSimpleMethod(method) %}
* @returns {Promise} - The promise which resolves to an array.
* The first element of the array is an object representing [{{- toMessageName(method.outputType) -}}]{@link {{ method.outputType.substring(1) }}}.
* The first element of the array is an object representing {{ typeLink(method.outputType) }}.
* The promise has a method named "cancel" which cancels the ongoing API call.
{%- endmacro -%}

{%- macro printReturnPagingServerMethod(method) %}
* @returns {Promise} - The promise which resolves to an array.
* The first element of the array is an object representing [{{- toMessageName(method.outputType) -}}]{@link {{ method.outputType.substring(1) }}}.
* The first element of the array is an object representing {{ typeLink(method.outputType) }}.
*
* When autoPaginate: false is specified through options, the array has three elements.
* The first element is Array of [{{- toMessageName(method.outputType) -}}]{@link {{ method.outputType.substring(1) }}} in a single response.
* The first element is Array of {{ typeLink(method.outputType) }} in a single response.
* The second element is the next request object if the response
* indicates the next page exists, or null. The third element is
* an object representing [{{- toMessageName(method.outputType) -}}]{@link {{ method.outputType.substring(1) }}}.
* an object representing {{ typeLink(method.outputType) }}.
*
* The promise has a method named "cancel" which cancels the ongoing API call.
{%- endmacro -%}


{%- macro printReturnClientStreamingMethod(method) %}
* @returns {Stream} - A writable stream which accepts objects representing
* [{{- toMessageName(method.inputType) -}}]{@link {{ method.inputType.substring(1) }}}.
* {{ typeLink(method.inputType) }}.
{%- endmacro -%}

{%- macro printReturnBidiStreamingMethod(method) %}
* @returns {Stream}
* An object stream which is both readable and writable. It accepts objects
* representing [{{- toMessageName(method.inputType) -}}]{@link {{ method.inputType.substring(1) }}} for write() method, and
* will emit objects representing [{{- toMessageName(method.outputType) -}}]{@link {{ method.outputType.substring(1) }}} on 'data' event asynchronously.
* representing {{ typeLink(method.inputType) }} for write() method, and
* will emit objects representing {{ typeLink(method.outputType) }} on 'data' event asynchronously.
{%- endmacro -%}

{%- macro printReturnPageStream(method) %}
* @returns {Stream}
* An object stream which emits an object representing [{{- toMessageName(method.pagingResponseType) -}}]{@link {{ method.pagingResponseType.substring(1) }}} on 'data' event.
* An object stream which emits an object representing {{ typeLink(method.pagingResponseType) }} on 'data' event.
{%- endmacro -%}


{%- macro printRequestField(oneComment) %}
{%- if oneComment.fieldBehavior and oneComment.fieldBehavior === 1 -%}
[request.{{ oneComment.paramName.toCamelCase() }}]
Expand All @@ -153,13 +156,22 @@ request.{{ oneComment.paramName.toCamelCase() }}
{%- endif -%}
{%- endmacro -%}

{%- macro typeLink(type) -%}
{%- set tsType = typescriptType(type) -%}
{%- if tsType.length > 0 -%}
{{ tsType }}
{%- else -%}
[{{- toMessageName(type) -}}]{@link {{ type.substring(1) }}}
{%- endif -%}
{%- endmacro -%}

{%- macro toMessageName(messageType) -%}
{%- set arr = messageType.split('.') %}
{{- arr[arr.length - 1] -}}
{%- endmacro -%}

{%- macro initRequestWithHeaderParam(method) -%}
const request: protosTypes{{ toInterface(method.inputInterface) }} = {};
const request: {{ toInterface(method.inputInterface) }} = {};
{%- if method.headerRequestParams.length > 1 %}
{%- set chain = "request" -%}
{%- for field in method.headerRequestParams.slice(0, -1) %}
Expand All @@ -170,20 +182,33 @@ request.{{ oneComment.paramName.toCamelCase() }}
{%- endif %}
{%- endmacro -%}

{%- macro typescriptType(protobufType) -%}
{#- protobufType can be an array (TYPE_STRING[]), hence .startsWith -#}
{%- if protobufType.startsWith('TYPE_BYTES') -%}
{%- set type = protobufType.replace('TYPE_BYTES', 'Buffer') -%}
{%- elif protobufType.startsWith('TYPE_BOOL') -%}
{%- set type = protobufType.replace('TYPE_BOOL', 'boolean') -%}
{%- elif protobufType.startsWith('TYPE_STRING') -%}
{%- set type = protobufType.replace('TYPE_STRING', 'string') -%}
{%- elif protobufType.startsWith('TYPE_') -%}
{#- any other type is essentially a number: int32, uint32, etc. -#}
{%- set type = protobufType.replace(r/TYPE_\w+/, 'number') -%}
{%- else -%}
{%- set type = '' -%}
{%- endif -%}
{{ type }}
{%- endmacro -%}

{%- macro toInterface(type) -%}
{%- set tsType = typescriptType(type) -%}
{%- if tsType.length > 0 -%}
{{ tsType }}
{%- else -%}
{%- set index = type.lastIndexOf('.') -%}
{{ type.substring(0, index + 1) + 'I' + type.substring(index + 1) }}
protosTypes{{ type.substring(0, index + 1) + 'I' + type.substring(index + 1) }}
{%- endif -%}
{%- endmacro -%}

{%- macro convertParamType(paramType) -%}
{%- if paramType.includes('TYPE_BYTES') %}
{%- set type = paramType.replace('TYPE_BYTES', 'Buffer') %}
{%- elif paramType.includes('TYPE_BOOL') %}
{%- set type = paramType.replace('TYPE_BOOL', 'boolean') %}
{%- elif paramType.includes('TYPE_STRING') %}
{%- set type = paramType.replace('TYPE_STRING', 'string') %}
{%- else %}
{%- set type = 'number' %}
{%- endif %}
{{- type -}}
{{- typescriptType(paramType) -}}
{%- endmacro -%}
108 changes: 54 additions & 54 deletions templates/typescript_gapic/src/$version/$service_client.ts.njk
Original file line number Diff line number Diff line change
Expand Up @@ -331,34 +331,34 @@ export class {{ service.name }}Client {

{%- for method in service.simpleMethods %}
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options?: gax.CallOptions):
Promise<[
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined
]>;
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options: gax.CallOptions,
callback: Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined,
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined,
{}|undefined>): void;
/**
{{- util.printComments(method, service) }}
*/
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
optionsOrCallback?: gax.CallOptions|Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>,
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>,
callback?: Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined,
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined,
{}|undefined>):
Promise<[
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined
]>|void {
request = request || {};
let options: gax.CallOptions;
Expand Down Expand Up @@ -398,7 +398,7 @@ export class {{ service.name }}Client {
{{- util.printComments(method, service) }}
*/
{{ method.name.toCamelCase() }}(
request?: protosTypes{{ util.toInterface(method.inputInterface) }},
request?: {{ util.toInterface(method.inputInterface) }},
options?: gax.CallOptions):
gax.CancellableStream{
request = request || {};
Expand All @@ -409,24 +409,24 @@ export class {{ service.name }}Client {
{{ method.name.toCamelCase() }}(
options: gax.CallOptions,
callback: Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
gax.CancellableStream;
{{ method.name.toCamelCase() }}(
callback: Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
gax.CancellableStream;
/**
{{- util.printComments(method, service) }}
*/
{{ method.name.toCamelCase() }}(
optionsOrCallback: gax.CallOptions|Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>,
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>,
callback?: Callback<
protosTypes{{ util.toInterface(method.outputInterface) }},
protosTypes{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
{{ util.toInterface(method.outputInterface) }},
{{ util.toInterface(method.inputInterface) }}|undefined, {}|undefined>):
gax.CancellableStream {
if (optionsOrCallback instanceof Function && callback === undefined) {
callback = optionsOrCallback;
Expand All @@ -439,34 +439,34 @@ export class {{ service.name }}Client {
{% endfor %}
{%- for method in service.longRunning %}
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options?: gax.CallOptions):
Promise<[
LROperation<protosTypes{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, protosTypes{{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
protosTypes{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined
LROperation<{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, {{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined
]>;
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options: gax.CallOptions,
callback: Callback<
LROperation<protosTypes{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, protosTypes{{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
protosTypes{{ util.toInterface(method.outputInterface) }}|undefined,
LROperation<{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, {{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
{{ util.toInterface(method.outputInterface) }}|undefined,
{}|undefined>): void;
/**
{{- util.printComments(method, service) }}
*/
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
optionsOrCallback?: gax.CallOptions|Callback<
LROperation<protosTypes{{ util.toInterface(method.longRunningResponseType, method.inputType)}}, protosTypes{{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
protosTypes{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined>,
LROperation<{{ util.toInterface(method.longRunningResponseType, method.inputType)}}, {{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined>,
callback?: Callback<
LROperation<protosTypes{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, protosTypes{{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
protosTypes{{ util.toInterface(method.outputInterface) }}|undefined,
LROperation<{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, {{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
{{ util.toInterface(method.outputInterface) }}|undefined,
{}|undefined>):
Promise<[
LROperation<protosTypes{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, protosTypes{{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
protosTypes{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined
LROperation<{{ util.toInterface(method.longRunningResponseType, method.inputType) }}, {{ util.toInterface(method.longRunningMetadataType, method.inputType) }}>,
{{ util.toInterface(method.outputInterface) }}|undefined, {}|undefined
]>|void {
request = request || {};
let options: gax.CallOptions;
Expand All @@ -492,37 +492,37 @@ export class {{ service.name }}Client {
{%- endfor %}
{%- for method in service.paging %}
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options?: gax.CallOptions):
Promise<[
protosTypes{{ util.toInterface(method.pagingResponseType) }}[],
protosTypes{{ util.toInterface(method.inputInterface) }}|null,
protosTypes{{ util.toInterface(method.outputInterface) }}
{{ util.toInterface(method.pagingResponseType) }}[],
{{ util.toInterface(method.inputInterface) }}|null,
{{ util.toInterface(method.outputInterface) }}
]>;
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
options: gax.CallOptions,
callback: Callback<
protosTypes{{ util.toInterface(method.pagingResponseType) }}[],
protosTypes{{ util.toInterface(method.inputInterface) }}|null,
protosTypes{{ util.toInterface(method.outputInterface) }}>): void;
{{ util.toInterface(method.pagingResponseType) }}[],
{{ util.toInterface(method.inputInterface) }}|null,
{{ util.toInterface(method.outputInterface) }}>): void;
/**
{{- util.printComments(method, service) }}
*/
{{ method.name.toCamelCase() }}(
request: protosTypes{{ util.toInterface(method.inputInterface) }},
request: {{ util.toInterface(method.inputInterface) }},
optionsOrCallback?: gax.CallOptions|Callback<
protosTypes{{ util.toInterface(method.pagingResponseType) }}[],
protosTypes{{ util.toInterface(method.inputInterface) }}|null,
protosTypes{{ util.toInterface(method.outputInterface) }}>,
{{ util.toInterface(method.pagingResponseType) }}[],
{{ util.toInterface(method.inputInterface) }}|null,
{{ util.toInterface(method.outputInterface) }}>,
callback?: Callback<
protosTypes{{ util.toInterface(method.pagingResponseType) }}[],
protosTypes{{ util.toInterface(method.inputInterface) }}|null,
protosTypes{{ util.toInterface(method.outputInterface) }}>):
{{ util.toInterface(method.pagingResponseType) }}[],
{{ util.toInterface(method.inputInterface) }}|null,
{{ util.toInterface(method.outputInterface) }}>):
Promise<[
protosTypes{{ util.toInterface(method.pagingResponseType) }}[],
protosTypes{{ util.toInterface(method.inputInterface) }}|null,
protosTypes{{ util.toInterface(method.outputInterface) }}
{{ util.toInterface(method.pagingResponseType) }}[],
{{ util.toInterface(method.inputInterface) }}|null,
{{ util.toInterface(method.outputInterface) }}
]>|void {
request = request || {};
let options: gax.CallOptions;
Expand Down Expand Up @@ -550,7 +550,7 @@ export class {{ service.name }}Client {
{{- util.printCommentsPageStream(method) }}
*/
{{ method.name.toCamelCase() }}Stream(
request?: protosTypes{{ util.toInterface(method.inputInterface) }},
request?: {{ util.toInterface(method.inputInterface) }},
options?: gax.CallOptions | {}):
Transform{
request = request || {};
Expand Down
10 changes: 9 additions & 1 deletion typescript/src/schema/proto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,15 @@ function pagingResponseType(
method: MethodDescriptorProto
) {
const field = pagingField(messages, method);
return field?.typeName; //.google.showcase.v1beta1.EchoResponse
if (!field || !field.type) {
return undefined;
}
if (
field.type === plugin.google.protobuf.FieldDescriptorProto.Type.TYPE_MESSAGE
) {
return field.typeName; //.google.showcase.v1beta1.EchoResponse
}
return plugin.google.protobuf.FieldDescriptorProto.Type[field.type];
}

export function getHeaderParams(rule: plugin.google.api.IHttpRule): string[] {
Expand Down

0 comments on commit 54b7ca8

Please sign in to comment.