diff --git a/.gitignore b/.gitignore index de9660172..acfbcffe6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ pbjs-genfiles/ .idea .test-out-keymanager .test-out-showcase +.test-out-translate .client_library *test-out* docker/package.tgz diff --git a/templates/typescript_gapic/src/$version/$service_client.ts.njk b/templates/typescript_gapic/src/$version/$service_client.ts.njk index 226c22913..dbad3f79a 100644 --- a/templates/typescript_gapic/src/$version/$service_client.ts.njk +++ b/templates/typescript_gapic/src/$version/$service_client.ts.njk @@ -55,7 +55,7 @@ export class {{ service.name }}Client { */ private _descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}}; private _innerApiCalls: {[name: string]: Function}; - {%- if (service.pathTemplate.length > 0) %} + {%- if (service.pathTemplates.length > 0) %} private _pathTemplates: {[name: string]: gax.PathTemplate}; {%- endif %} auth: gax.GoogleAuth; @@ -144,10 +144,10 @@ export class {{ service.name }}Client { require("../../protos/protos.json") : nodejsProtoPath ); -{%- if (service.pathTemplate.length > 0) %} +{%- if (service.pathTemplates.length > 0) %} this._pathTemplates = { -{%- for template in service.pathTemplate %} - {{ template.type.toCamelCase() }}PathTemplate: new gaxModule.PathTemplate( +{%- for template in service.pathTemplates %} + {{ template.name.toCamelCase() }}PathTemplate: new gaxModule.PathTemplate( '{{ template.pattern }}' ), {%- endfor %} @@ -495,26 +495,26 @@ export class {{ service.name }}Client { return this._innerApiCalls.{{ method.name.toCamelCase() }}(request, options, callback); } {%- endfor %} -{%- if (service.pathTemplate.length > 0) %} +{%- if (service.pathTemplates.length > 0) %} // -------------------- // -- Path templates -- // -------------------- -{%- for template in service.pathTemplate %} - {{ template.type.toLowerCase() }}Path( +{%- for template in service.pathTemplates %} + {{ template.name.toLowerCase() }}Path( {%- set paramJoiner = joiner() %} {%- for param in template.params %} {{-paramJoiner()-}}{{ param }}:string {%- endfor -%} ){ - return this._pathTemplates.{{ template.type.toLowerCase() }}PathTemplate.render({ + return this._pathTemplates.{{ template.name.toLowerCase() }}PathTemplate.render({ {%- for param in template.params %} {{ param }}: {{ param }}, {%- endfor %} }); } {%- for param in template.params %} - match{{ param.capitalize() }}From{{ template.type }}Name({{ template.type.toLowerCase() }}Name: string){ - return this._pathTemplates.{{ template.type.toLowerCase() }}PathTemplate.match({{ template.type.toLowerCase() }}Name).{{ param }}; + match{{ param.capitalize() }}From{{ template.name }}Name({{ template.name.toLowerCase() }}Name: string){ + return this._pathTemplates.{{ template.name.toLowerCase() }}PathTemplate.match({{ template.name.toLowerCase() }}Name).{{ param }}; } {%- endfor %} {%- endfor %} diff --git a/typescript/src/schema/api.ts b/typescript/src/schema/api.ts index ebab868e2..de917753b 100644 --- a/typescript/src/schema/api.ts +++ b/typescript/src/schema/api.ts @@ -1,7 +1,7 @@ import * as plugin from '../../../pbjs-genfiles/plugin'; import { Naming } from './naming'; -import { Proto } from './proto'; +import { Proto, MessagesMap, ResourceDescriptor, ResourceMap } from './proto'; import { fstat } from 'fs-extra'; export interface ProtosMap { @@ -26,11 +26,19 @@ export class API { fd => fd.package && fd.package.startsWith(packageName) ) ); + // construct resource map + const resourceMap = getResourceMap(fileDescriptors); + // parse resource map to Proto constructor this.protos = fileDescriptors .filter(fd => fd.name) .reduce( (map, fd) => { - map[fd.name!] = new Proto(fd, packageName, grpcServiceConfig); + map[fd.name!] = new Proto( + fd, + packageName, + grpcServiceConfig, + resourceMap + ); return map; }, {} as ProtosMap @@ -83,3 +91,80 @@ export class API { ); } } + +function getResourceMap( + fileDescriptors: plugin.google.protobuf.IFileDescriptorProto[] +): ResourceMap { + const resourceMap: ResourceMap = {}; + for (const fd of fileDescriptors) { + if (fd && fd.messageType) { + const messages = fd.messageType + .filter(message => message.name) + .reduce( + (map, message) => { + map['.' + fd.package! + '.' + message.name!] = message; + return map; + }, + {} as MessagesMap + ); + for (const property of Object.keys(messages)) { + const m = messages[property]; + if (m && m.options) { + const option = m.options; + if (option && option['.google.api.resource']) { + const opt = option['.google.api.resource']; + const oneResource = option[ + '.google.api.resource' + ] as ResourceDescriptor; + if (opt.type) { + const arr = opt.type.match(/\/([^.]+)$/); + if (arr && arr[1]) { + oneResource.name = arr[1]; + } + } else { + console.warn( + 'In file ' + + fd.name + + ' message ' + + property + + ' refers to a resource which does not have a type: ' + + opt + ); + continue; + } + const pattern = opt.pattern; + if (pattern && pattern[0]) { + const params = pattern[0].match(/{[a-zA-Z]+}/g) || []; + for (let i = 0; i < params.length; i++) { + params[i] = params[i].replace('{', '').replace('}', ''); + } + oneResource.params = params; + } + if (oneResource.name && oneResource.params) { + resourceMap[opt.type!] = oneResource; + } else if (oneResource.name) { + console.warn( + 'In file ' + + fd.name + + ' message ' + + property + + ' refers to a resource which does not have a proper pattern : ' + + opt + ); + } else { + console.warn( + 'In file ' + + fd.name + + ' message ' + + property + + ' refers to a resource which does not have a proper name : ' + + opt + ); + } + } + } + } + } + } + return resourceMap; +} diff --git a/typescript/src/schema/proto.ts b/typescript/src/schema/proto.ts index 14c2a9b18..1786790cb 100644 --- a/typescript/src/schema/proto.ts +++ b/typescript/src/schema/proto.ts @@ -158,7 +158,7 @@ interface ServiceDescriptorProto port: number; oauthScopes: string[]; comments: string; - pathTemplate: ResourceDescriptor[]; + pathTemplates: ResourceDescriptor[]; commentsMap: CommentsMap; retryableCodeMap: RetryableCodeMap; grpcServiceConfig: plugin.grpc.service_config.ServiceConfig; @@ -166,9 +166,14 @@ interface ServiceDescriptorProto export interface ResourceDescriptor extends plugin.google.api.IResourceDescriptor { + name: string; params: string[]; } +export interface ResourceMap { + [name: string]: ResourceDescriptor; +} + export interface ServicesMap { [name: string]: ServiceDescriptorProto; } @@ -385,7 +390,8 @@ function augmentService( packageName: string, service: plugin.google.protobuf.IServiceDescriptorProto, commentsMap: CommentsMap, - grpcServiceConfig: plugin.grpc.service_config.ServiceConfig + grpcServiceConfig: plugin.grpc.service_config.ServiceConfig, + resourceMap: ResourceMap ) { const augmentedService = service as ServiceDescriptorProto; augmentedService.packageName = packageName; @@ -442,32 +448,33 @@ function augmentService( '.google.api.oauthScopes' ].split(','); } - augmentedService.pathTemplate = []; + augmentedService.pathTemplates = []; for (const property of Object.keys(messages)) { const m = messages[property]; - if (m && m.options) { - const option = m.options; - if (option && option['.google.api.resource']) { - const opt = option['.google.api.resource']; - const onePathTemplate = option[ - '.google.api.resource' - ] as ResourceDescriptor; - if (opt.type) { - const arr = opt.type.match(/\/([^.]+)$/); - if (arr) { - opt.type = arr[arr.length - 1]; - } - } - const pattern = opt.pattern; - //TODO: SUPPORT MULTIPLE PATTERNS - if (pattern && pattern[0]) { - const params = pattern[0].match(/{[a-zA-Z]+}/g) || []; - for (let i = 0; i < params.length; i++) { - params[i] = params[i].replace('{', '').replace('}', ''); + if (m && m.field) { + const fields = m.field; + for (const fieldDescriptor of fields) { + if (fieldDescriptor && fieldDescriptor.options) { + const option = fieldDescriptor.options; + if (option && option['.google.api.resourceReference']) { + const resourceReference = option['.google.api.resourceReference']; + const type = resourceReference.type; + if (!type || !resourceMap[type.toString()]) { + console.warn( + 'In service proto ' + + service.name + + ' message ' + + property + + ' refers to an unkown resource: ' + + resourceReference + ); + continue; + } + const resource = resourceMap[resourceReference.type!.toString()]; + if (augmentedService.pathTemplates.includes(resource)) continue; + augmentedService.pathTemplates.push(resource); } - onePathTemplate.params = params; } - augmentedService.pathTemplate.push(onePathTemplate); } } } @@ -485,7 +492,8 @@ export class Proto { constructor( fd: plugin.google.protobuf.IFileDescriptorProto, packageName: string, - grpcServiceConfig: plugin.grpc.service_config.ServiceConfig + grpcServiceConfig: plugin.grpc.service_config.ServiceConfig, + resourceMap: ResourceMap ) { fd.enumType = fd.enumType || []; fd.messageType = fd.messageType || []; @@ -525,7 +533,8 @@ export class Proto { packageName, service, commentsMap, - grpcServiceConfig + grpcServiceConfig, + resourceMap ) ) .reduce( diff --git a/typescript/test/protos/google/cloud/common_resources.proto b/typescript/test/protos/google/cloud/common_resources.proto new file mode 100644 index 000000000..5d795bff1 --- /dev/null +++ b/typescript/test/protos/google/cloud/common_resources.proto @@ -0,0 +1,68 @@ +// Copyright 2019 Google LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This file contains stub messages for common resources in GCP. +// It is not intended to be directly generated, and is instead used by +// other tooling to be able to match common resource patterns. +syntax = "proto3"; + +package google.cloud; + +import "google/api/resource.proto"; + + +message Project { + option (google.api.resource) = { + type: "cloudresourcemanager.googleapis.com/Project" + pattern: "projects/{project}" + }; + + string name = 1; +} + +message Organization { + option (google.api.resource) = { + type: "cloudresourcemanager.googleapis.com/Organization" + pattern: "organizations/{organization}" + }; + + string name = 1; +} + +message Folder { + option (google.api.resource) = { + type: "cloudresourcemanager.googleapis.com/Folder" + pattern: "folders/{folder}" + }; + + string name = 1; +} + +message BillingAccount { + option (google.api.resource) = { + type: "cloudbilling.googleapis.com/BillingAccount" + pattern: "billingAccounts/{billing_account}" + }; + + string name = 1; +} + +message Location { + option (google.api.resource) = { + type: "locations.googleapis.com/Location" + pattern: "projects/{project}/locations/{location}" + }; + + string name = 1; +} diff --git a/typescript/test/protos/google/cloud/translate/v3beta1/translation_service.proto b/typescript/test/protos/google/cloud/translate/v3beta1/translation_service.proto new file mode 100644 index 000000000..e62a50883 --- /dev/null +++ b/typescript/test/protos/google/cloud/translate/v3beta1/translation_service.proto @@ -0,0 +1,902 @@ +// Copyright 2019 Google LLC. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +syntax = "proto3"; + +package google.cloud.translation.v3beta1; + +import "google/api/annotations.proto"; +import "google/api/client.proto"; +import "google/api/field_behavior.proto"; +import "google/api/resource.proto"; +import "google/longrunning/operations.proto"; +import "google/protobuf/timestamp.proto"; + +option cc_enable_arenas = true; +option csharp_namespace = "Google.Cloud.Translate.V3Beta1"; +option go_package = "google.golang.org/genproto/googleapis/cloud/translate/v3beta1;translate"; +option java_multiple_files = true; +option java_outer_classname = "TranslationServiceProto"; +option java_package = "com.google.cloud.translate.v3beta1"; +option php_namespace = "Google\\Cloud\\Translate\\V3beta1"; +option ruby_package = "Google::Cloud::Translate::V3beta1"; + +// Proto file for the Cloud Translation API (v3beta1). + +// Provides natural language translation operations. +service TranslationService { + option (google.api.default_host) = "translate.googleapis.com"; + option (google.api.oauth_scopes) = + "https://www.googleapis.com/auth/cloud-platform," + "https://www.googleapis.com/auth/cloud-translation"; + + // Translates input text and returns translated text. + rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) { + option (google.api.http) = { + post: "/v3beta1/{parent=projects/*/locations/*}:translateText" + body: "*" + additional_bindings { + post: "/v3beta1/{parent=projects/*}:translateText" + body: "*" + } + }; + } + + // Detects the language of text within a request. + rpc DetectLanguage(DetectLanguageRequest) returns (DetectLanguageResponse) { + option (google.api.http) = { + post: "/v3beta1/{parent=projects/*/locations/*}:detectLanguage" + body: "*" + additional_bindings { + post: "/v3beta1/{parent=projects/*}:detectLanguage" + body: "*" + } + }; + option (google.api.method_signature) = "parent,model,mime_type"; + } + + // Returns a list of supported languages for translation. + rpc GetSupportedLanguages(GetSupportedLanguagesRequest) returns (SupportedLanguages) { + option (google.api.http) = { + get: "/v3beta1/{parent=projects/*/locations/*}/supportedLanguages" + additional_bindings { + get: "/v3beta1/{parent=projects/*}/supportedLanguages" + } + }; + option (google.api.method_signature) = "parent,display_language_code,model"; + } + + // Translates a large volume of text in asynchronous batch mode. + // This function provides real-time output as the inputs are being processed. + // If caller cancels a request, the partial results (for an input file, it's + // all or nothing) may still be available on the specified output location. + // + // This call returns immediately and you can + // use google.longrunning.Operation.name to poll the status of the call. + rpc BatchTranslateText(BatchTranslateTextRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v3beta1/{parent=projects/*/locations/*}:batchTranslateText" + body: "*" + }; + option (google.longrunning.operation_info) = { + response_type: "BatchTranslateResponse" + metadata_type: "BatchTranslateMetadata" + }; + } + + // Creates a glossary and returns the long-running operation. Returns + // NOT_FOUND, if the project doesn't exist. + rpc CreateGlossary(CreateGlossaryRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + post: "/v3beta1/{parent=projects/*/locations/*}/glossaries" + body: "glossary" + }; + option (google.api.method_signature) = "parent,glossary"; + option (google.longrunning.operation_info) = { + response_type: "Glossary" + metadata_type: "CreateGlossaryMetadata" + }; + } + + // Lists glossaries in a project. Returns NOT_FOUND, if the project doesn't + // exist. + rpc ListGlossaries(ListGlossariesRequest) returns (ListGlossariesResponse) { + option (google.api.http) = { + get: "/v3beta1/{parent=projects/*/locations/*}/glossaries" + }; + option (google.api.method_signature) = "parent"; + option (google.api.method_signature) = "parent,filter"; + } + + // Gets a glossary. Returns NOT_FOUND, if the glossary doesn't + // exist. + rpc GetGlossary(GetGlossaryRequest) returns (Glossary) { + option (google.api.http) = { + get: "/v3beta1/{name=projects/*/locations/*/glossaries/*}" + }; + option (google.api.method_signature) = "name"; + } + + // Deletes a glossary, or cancels glossary construction + // if the glossary isn't created yet. + // Returns NOT_FOUND, if the glossary doesn't exist. + rpc DeleteGlossary(DeleteGlossaryRequest) returns (google.longrunning.Operation) { + option (google.api.http) = { + delete: "/v3beta1/{name=projects/*/locations/*/glossaries/*}" + }; + option (google.api.method_signature) = "name"; + option (google.longrunning.operation_info) = { + response_type: "DeleteGlossaryResponse" + metadata_type: "DeleteGlossaryMetadata" + }; + } +} + +// Configures which glossary should be used for a specific target language, +// and defines options for applying that glossary. +message TranslateTextGlossaryConfig { + // Required. Specifies the glossary used for this translation. Use + // this format: projects/*/locations/*/glossaries/* + string glossary = 1 [(google.api.field_behavior) = REQUIRED]; + + // Optional. Indicates match is case-insensitive. + // Default value is false if missing. + bool ignore_case = 2 [(google.api.field_behavior) = OPTIONAL]; +} + +// The request message for synchronous translation. +message TranslateTextRequest { + // Required. The content of the input in string format. + // We recommend the total content be less than 30k codepoints. + // Use BatchTranslateText for larger text. + repeated string contents = 1 [(google.api.field_behavior) = REQUIRED]; + + // Optional. The format of the source text, for example, "text/html", + // "text/plain". If left blank, the MIME type defaults to "text/html". + string mime_type = 3 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. The BCP-47 language code of the input text if + // known, for example, "en-US" or "sr-Latn". Supported language codes are + // listed in Language Support. If the source language isn't specified, the API + // attempts to identify the source language automatically and returns the + // source language within the response. + string source_language_code = 4 [(google.api.field_behavior) = OPTIONAL]; + + // Required. The BCP-47 language code to use for translation of the input + // text, set to one of the language codes listed in Language Support. + string target_language_code = 5 [(google.api.field_behavior) = REQUIRED]; + + // Required. Project or location to make a call. Must refer to a caller's + // project. + // + // Format: `projects/{project-id}` or + // `projects/{project-id}/locations/{location-id}`. + // + // For global calls, use `projects/{project-id}/locations/global` or + // `projects/{project-id}`. + // + // Non-global location is required for requests using AutoML models or + // custom glossaries. + // + // Models and glossaries must be within the same region (have same + // location-id), otherwise an INVALID_ARGUMENT (400) error is returned. + string parent = 8 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Optional. The `model` type requested for this translation. + // + // The format depends on model type: + // + // - AutoML Translation models: + // `projects/{project-id}/locations/{location-id}/models/{model-id}` + // + // - General (built-in) models: + // `projects/{project-id}/locations/{location-id}/models/general/nmt`, + // `projects/{project-id}/locations/{location-id}/models/general/base` + // + // + // For global (non-regionalized) requests, use `location-id` `global`. + // For example, + // `projects/{project-id}/locations/global/models/general/nmt`. + // + // If missing, the system decides which google base model to use. + string model = 6 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. Glossary to be applied. The glossary must be + // within the same region (have the same location-id) as the model, otherwise + // an INVALID_ARGUMENT (400) error is returned. + TranslateTextGlossaryConfig glossary_config = 7 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. The labels with user-defined metadata for the request. + // + // Label keys and values can be no longer than 63 characters + // (Unicode codepoints), can only contain lowercase letters, numeric + // characters, underscores and dashes. International characters are allowed. + // Label values are optional. Label keys must start with a letter. + // + // See https://cloud.google.com/translate/docs/labels for more information. + map labels = 10 [(google.api.field_behavior) = OPTIONAL]; +} + +message TranslateTextResponse { + // Text translation responses with no glossary applied. + // This field has the same length as + // [`contents`][google.cloud.translation.v3beta1.TranslateTextRequest.contents]. + repeated Translation translations = 1; + + // Text translation responses if a glossary is provided in the request. + // This can be the same as + // [`translations`][google.cloud.translation.v3beta1.TranslateTextResponse.translations] if no terms apply. + // This field has the same length as + // [`contents`][google.cloud.translation.v3beta1.TranslateTextRequest.contents]. + repeated Translation glossary_translations = 3; +} + +// A single translation response. +message Translation { + // Text translated into the target language. + string translated_text = 1; + + // Only present when `model` is present in the request. + // This is same as `model` provided in the request. + string model = 2; + + // The BCP-47 language code of source text in the initial request, detected + // automatically, if no source language was passed within the initial + // request. If the source language was passed, auto-detection of the language + // does not occur and this field is empty. + string detected_language_code = 4; + + // The `glossary_config` used for this translation. + TranslateTextGlossaryConfig glossary_config = 3; +} + +// The request message for language detection. +message DetectLanguageRequest { + // Required. Project or location to make a call. Must refer to a caller's + // project. + // + // Format: `projects/{project-id}/locations/{location-id}` or + // `projects/{project-id}`. + // + // For global calls, use `projects/{project-id}/locations/global` or + // `projects/{project-id}`. + // + // Only models within the same region (has same location-id) can be used. + // Otherwise an INVALID_ARGUMENT (400) error is returned. + string parent = 5 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Optional. The language detection model to be used. + // + // Format: + // `projects/{project-id}/locations/{location-id}/models/language-detection/{model-id}` + // + // Only one language detection model is currently supported: + // `projects/{project-id}/locations/{location-id}/models/language-detection/default`. + // + // If not specified, the default model is used. + string model = 4 [(google.api.field_behavior) = OPTIONAL]; + + // Required. The source of the document from which to detect the language. + oneof source { + // The content of the input stored as a string. + string content = 1; + } + + // Optional. The format of the source text, for example, "text/html", + // "text/plain". If left blank, the MIME type defaults to "text/html". + string mime_type = 3 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. The labels with user-defined metadata for the request. + // + // Label keys and values can be no longer than 63 characters + // (Unicode codepoints), can only contain lowercase letters, numeric + // characters, underscores and dashes. International characters are allowed. + // Label values are optional. Label keys must start with a letter. + // + // See https://cloud.google.com/translate/docs/labels for more information. + map labels = 6; +} + +// The response message for language detection. +message DetectedLanguage { + // The BCP-47 language code of source content in the request, detected + // automatically. + string language_code = 1; + + // The confidence of the detection result for this language. + float confidence = 2; +} + +// The response message for language detection. +message DetectLanguageResponse { + // A list of detected languages sorted by detection confidence in descending + // order. The most probable language first. + repeated DetectedLanguage languages = 1; +} + +// The request message for discovering supported languages. +message GetSupportedLanguagesRequest { + // Required. Project or location to make a call. Must refer to a caller's + // project. + // + // Format: `projects/{project-id}` or + // `projects/{project-id}/locations/{location-id}`. + // + // For global calls, use `projects/{project-id}/locations/global` or + // `projects/{project-id}`. + // + // Non-global location is required for AutoML models. + // + // Only models within the same region (have same location-id) can be used, + // otherwise an INVALID_ARGUMENT (400) error is returned. + string parent = 3 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Optional. The language to use to return localized, human readable names + // of supported languages. If missing, then display names are not returned + // in a response. + string display_language_code = 1 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. Get supported languages of this model. + // + // The format depends on model type: + // + // - AutoML Translation models: + // `projects/{project-id}/locations/{location-id}/models/{model-id}` + // + // - General (built-in) models: + // `projects/{project-id}/locations/{location-id}/models/general/nmt`, + // `projects/{project-id}/locations/{location-id}/models/general/base` + // + // + // Returns languages supported by the specified model. + // If missing, we get supported languages of Google general base (PBMT) model. + string model = 2 [(google.api.field_behavior) = OPTIONAL]; +} + +// The response message for discovering supported languages. +message SupportedLanguages { + // A list of supported language responses. This list contains an entry + // for each language the Translation API supports. + repeated SupportedLanguage languages = 1; +} + +// A single supported language response corresponds to information related +// to one supported language. +message SupportedLanguage { + // Supported language code, generally consisting of its ISO 639-1 + // identifier, for example, 'en', 'ja'. In certain cases, BCP-47 codes + // including language and region identifiers are returned (for example, + // 'zh-TW' and 'zh-CN') + string language_code = 1; + + // Human readable name of the language localized in the display language + // specified in the request. + string display_name = 2; + + // Can be used as source language. + bool support_source = 3; + + // Can be used as target language. + bool support_target = 4; +} + +// The Google Cloud Storage location for the input content. +message GcsSource { + // Required. Source data URI. For example, `gs://my_bucket/my_object`. + string input_uri = 1 [(google.api.field_behavior) = REQUIRED]; +} + +// Input configuration for BatchTranslateText request. +message InputConfig { + // Optional. Can be "text/plain" or "text/html". + // For `.tsv`, "text/html" is used if mime_type is missing. + // For `.html`, this field must be "text/html" or empty. + // For `.txt`, this field must be "text/plain" or empty. + string mime_type = 1 [(google.api.field_behavior) = OPTIONAL]; + + // Required. Specify the input. + oneof source { + // Required. Google Cloud Storage location for the source input. + // This can be a single file (for example, + // `gs://translation-test/input.tsv`) or a wildcard (for example, + // `gs://translation-test/*`). If a file extension is `.tsv`, it can + // contain either one or two columns. The first column (optional) is the id + // of the text request. If the first column is missing, we use the row + // number (0-based) from the input file as the ID in the output file. The + // second column is the actual text to be + // translated. We recommend each row be <= 10K Unicode codepoints, + // otherwise an error might be returned. + // Note that the input tsv must be RFC 4180 compliant. + // + // You could use https://github.com/Clever/csvlint to check potential + // formatting errors in your tsv file. + // csvlint --delimiter='\t' your_input_file.tsv + // + // The other supported file extensions are `.txt` or `.html`, which is + // treated as a single large chunk of text. + GcsSource gcs_source = 2; + } +} + +// The Google Cloud Storage location for the output content. +message GcsDestination { + // Required. There must be no files under 'output_uri_prefix'. + // 'output_uri_prefix' must end with "/" and start with "gs://", otherwise an + // INVALID_ARGUMENT (400) error is returned. + string output_uri_prefix = 1 [(google.api.field_behavior) = REQUIRED]; +} + +// Output configuration for BatchTranslateText request. +message OutputConfig { + // Required. The destination of output. + oneof destination { + // Google Cloud Storage destination for output content. + // For every single input file (for example, gs://a/b/c.[extension]), we + // generate at most 2 * n output files. (n is the # of target_language_codes + // in the BatchTranslateTextRequest). + // + // Output files (tsv) generated are compliant with RFC 4180 except that + // record delimiters are '\n' instead of '\r\n'. We don't provide any way to + // change record delimiters. + // + // While the input files are being processed, we write/update an index file + // 'index.csv' under 'output_uri_prefix' (for example, + // gs://translation-test/index.csv) The index file is generated/updated as + // new files are being translated. The format is: + // + // input_file,target_language_code,translations_file,errors_file, + // glossary_translations_file,glossary_errors_file + // + // input_file is one file we matched using gcs_source.input_uri. + // target_language_code is provided in the request. + // translations_file contains the translations. (details provided below) + // errors_file contains the errors during processing of the file. (details + // below). Both translations_file and errors_file could be empty + // strings if we have no content to output. + // glossary_translations_file and glossary_errors_file are always empty + // strings if the input_file is tsv. They could also be empty if we have no + // content to output. + // + // Once a row is present in index.csv, the input/output matching never + // changes. Callers should also expect all the content in input_file are + // processed and ready to be consumed (that is, no partial output file is + // written). + // + // The format of translations_file (for target language code 'trg') is: + // gs://translation_test/a_b_c_'trg'_translations.[extension] + // + // If the input file extension is tsv, the output has the following + // columns: + // Column 1: ID of the request provided in the input, if it's not + // provided in the input, then the input row number is used (0-based). + // Column 2: source sentence. + // Column 3: translation without applying a glossary. Empty string if there + // is an error. + // Column 4 (only present if a glossary is provided in the request): + // translation after applying the glossary. Empty string if there is an + // error applying the glossary. Could be same string as column 3 if there is + // no glossary applied. + // + // If input file extension is a txt or html, the translation is directly + // written to the output file. If glossary is requested, a separate + // glossary_translations_file has format of + // gs://translation_test/a_b_c_'trg'_glossary_translations.[extension] + // + // The format of errors file (for target language code 'trg') is: + // gs://translation_test/a_b_c_'trg'_errors.[extension] + // + // If the input file extension is tsv, errors_file contains the following: + // Column 1: ID of the request provided in the input, if it's not + // provided in the input, then the input row number is used (0-based). + // Column 2: source sentence. + // Column 3: Error detail for the translation. Could be empty. + // Column 4 (only present if a glossary is provided in the request): + // Error when applying the glossary. + // + // If the input file extension is txt or html, glossary_error_file will be + // generated that contains error details. glossary_error_file has format of + // gs://translation_test/a_b_c_'trg'_glossary_errors.[extension] + GcsDestination gcs_destination = 1; + } +} + +// The batch translation request. +message BatchTranslateTextRequest { + // Required. Location to make a call. Must refer to a caller's project. + // + // Format: `projects/{project-id}/locations/{location-id}`. + // + // The `global` location is not supported for batch translation. + // + // Only AutoML Translation models or glossaries within the same region (have + // the same location-id) can be used, otherwise an INVALID_ARGUMENT (400) + // error is returned. + string parent = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Required. Source language code. + string source_language_code = 2 [(google.api.field_behavior) = REQUIRED]; + + // Required. Specify up to 10 language codes here. + repeated string target_language_codes = 3 [(google.api.field_behavior) = REQUIRED]; + + // Optional. The models to use for translation. Map's key is target language + // code. Map's value is model name. Value can be a built-in general model, + // or an AutoML Translation model. + // + // The value format depends on model type: + // + // - AutoML Translation models: + // `projects/{project-id}/locations/{location-id}/models/{model-id}` + // + // - General (built-in) models: + // `projects/{project-id}/locations/{location-id}/models/general/nmt`, + // `projects/{project-id}/locations/{location-id}/models/general/base` + // + // + // If the map is empty or a specific model is + // not requested for a language pair, then default google model (nmt) is used. + map models = 4 [(google.api.field_behavior) = OPTIONAL]; + + // Required. Input configurations. + // The total number of files matched should be <= 1000. + // The total content size should be <= 100M Unicode codepoints. + // The files must use UTF-8 encoding. + repeated InputConfig input_configs = 5 [(google.api.field_behavior) = REQUIRED]; + + // Required. Output configuration. + // If 2 input configs match to the same file (that is, same input path), + // we don't generate output for duplicate inputs. + OutputConfig output_config = 6 [(google.api.field_behavior) = REQUIRED]; + + // Optional. Glossaries to be applied for translation. + // It's keyed by target language code. + map glossaries = 7 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. The labels with user-defined metadata for the request. + // + // Label keys and values can be no longer than 63 characters + // (Unicode codepoints), can only contain lowercase letters, numeric + // characters, underscores and dashes. International characters are allowed. + // Label values are optional. Label keys must start with a letter. + // + // See https://cloud.google.com/translate/docs/labels for more information. + map labels = 9 [(google.api.field_behavior) = OPTIONAL]; +} + +// State metadata for the batch translation operation. +message BatchTranslateMetadata { + // State of the job. + enum State { + // Invalid. + STATE_UNSPECIFIED = 0; + + // Request is being processed. + RUNNING = 1; + + // The batch is processed, and at least one item was successfully + // processed. + SUCCEEDED = 2; + + // The batch is done and no item was successfully processed. + FAILED = 3; + + // Request is in the process of being canceled after caller invoked + // longrunning.Operations.CancelOperation on the request id. + CANCELLING = 4; + + // The batch is done after the user has called the + // longrunning.Operations.CancelOperation. Any records processed before the + // cancel command are output as specified in the request. + CANCELLED = 5; + } + + // The state of the operation. + State state = 1; + + // Number of successfully translated characters so far (Unicode codepoints). + int64 translated_characters = 2; + + // Number of characters that have failed to process so far (Unicode + // codepoints). + int64 failed_characters = 3; + + // Total number of characters (Unicode codepoints). + // This is the total number of codepoints from input files times the number of + // target languages and appears here shortly after the call is submitted. + int64 total_characters = 4; + + // Time when the operation was submitted. + google.protobuf.Timestamp submit_time = 5; +} + +// Stored in the [google.longrunning.Operation.response][google.longrunning.Operation.response] field returned by +// BatchTranslateText if at least one sentence is translated successfully. +message BatchTranslateResponse { + // Total number of characters (Unicode codepoints). + int64 total_characters = 1; + + // Number of successfully translated characters (Unicode codepoints). + int64 translated_characters = 2; + + // Number of characters that have failed to process (Unicode codepoints). + int64 failed_characters = 3; + + // Time when the operation was submitted. + google.protobuf.Timestamp submit_time = 4; + + // The time when the operation is finished and + // [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. + google.protobuf.Timestamp end_time = 5; +} + +// Input configuration for glossaries. +message GlossaryInputConfig { + // Required. Specify the input. + oneof source { + // Required. Google Cloud Storage location of glossary data. + // File format is determined based on the filename extension. API returns + // [google.rpc.Code.INVALID_ARGUMENT] for unsupported URI-s and file + // formats. Wildcards are not allowed. This must be a single file in one of + // the following formats: + // + // For unidirectional glossaries: + // + // - TSV/CSV (`.tsv`/`.csv`): 2 column file, tab- or comma-separated. + // The first column is source text. The second column is target text. + // The file must not contain headers. That is, the first row is data, not + // column names. + // + // - TMX (`.tmx`): TMX file with parallel data defining source/target term + // pairs. + // + // For equivalent term sets glossaries: + // + // - CSV (`.csv`): Multi-column CSV file defining equivalent glossary terms + // in multiple languages. The format is defined for Google Translation + // Toolkit and documented in [Use a + // glossary](https://support.google.com/translatortoolkit/answer/6306379?hl=en). + GcsSource gcs_source = 1; + } +} + +// Represents a glossary built from user provided data. +message Glossary { + option (google.api.resource) = { + type: "translate.googleapis.com/Glossary" + pattern: "projects/{project}/locations/{location}/glossaries/{glossary}" + }; + + // Used with unidirectional glossaries. + message LanguageCodePair { + // Required. The BCP-47 language code of the input text, for example, + // "en-US". Expected to be an exact match for GlossaryTerm.language_code. + string source_language_code = 1; + + // Required. The BCP-47 language code for translation output, for example, + // "zh-CN". Expected to be an exact match for GlossaryTerm.language_code. + string target_language_code = 2; + } + + // Used with equivalent term set glossaries. + message LanguageCodesSet { + // The BCP-47 language code(s) for terms defined in the glossary. + // All entries are unique. The list contains at least two entries. + // Expected to be an exact match for GlossaryTerm.language_code. + repeated string language_codes = 1; + } + + // Required. The resource name of the glossary. Glossary names have the form + // `projects/{project-id}/locations/{location-id}/glossaries/{glossary-id}`. + string name = 1 [(google.api.field_behavior) = REQUIRED]; + + // Languages supported by the glossary. + oneof languages { + // Used with unidirectional glossaries. + LanguageCodePair language_pair = 3; + + // Used with equivalent term set glossaries. + LanguageCodesSet language_codes_set = 4; + } + + // Required. Provides examples to build the glossary from. + // Total glossary must not exceed 10M Unicode codepoints. + GlossaryInputConfig input_config = 5; + + // Output only. The number of entries defined in the glossary. + int32 entry_count = 6 [(google.api.field_behavior) = OUTPUT_ONLY]; + + // Output only. When CreateGlossary was called. + google.protobuf.Timestamp submit_time = 7 [(google.api.field_behavior) = OUTPUT_ONLY]; + + // Output only. When the glossary creation was finished. + google.protobuf.Timestamp end_time = 8 [(google.api.field_behavior) = OUTPUT_ONLY]; +} + +// Request message for CreateGlossary. +message CreateGlossaryRequest { + // Required. The project name. + string parent = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Required. The glossary to create. + Glossary glossary = 2 [(google.api.field_behavior) = REQUIRED]; +} + +// Request message for GetGlossary. +message GetGlossaryRequest { + // Required. The name of the glossary to retrieve. + string name = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "translate.googleapis.com/Glossary" + } + ]; +} + +// Request message for DeleteGlossary. +message DeleteGlossaryRequest { + // Required. The name of the glossary to delete. + string name = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "translate.googleapis.com/Glossary" + } + ]; +} + +// Request message for ListGlossaries. +message ListGlossariesRequest { + // Required. The name of the project from which to list all of the glossaries. + string parent = 1 [ + (google.api.field_behavior) = REQUIRED, + (google.api.resource_reference) = { + type: "locations.googleapis.com/Location" + } + ]; + + // Optional. Requested page size. The server may return fewer glossaries than + // requested. If unspecified, the server picks an appropriate default. + int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. A token identifying a page of results the server should return. + // Typically, this is the value of [ListGlossariesResponse.next_page_token] + // returned from the previous call to `ListGlossaries` method. + // The first page is returned if `page_token`is empty or missing. + string page_token = 3 [(google.api.field_behavior) = OPTIONAL]; + + // Optional. Filter specifying constraints of a list operation. + // Filtering is not supported yet, and the parameter currently has no effect. + // If missing, no filtering is performed. + string filter = 4 [(google.api.field_behavior) = OPTIONAL]; +} + +// Response message for ListGlossaries. +message ListGlossariesResponse { + // The list of glossaries for a project. + repeated Glossary glossaries = 1; + + // A token to retrieve a page of results. Pass this value in the + // [ListGlossariesRequest.page_token] field in the subsequent call to + // `ListGlossaries` method to retrieve the next page of results. + string next_page_token = 2; +} + +// Stored in the [google.longrunning.Operation.metadata][google.longrunning.Operation.metadata] field returned by +// CreateGlossary. +message CreateGlossaryMetadata { + // Enumerates the possible states that the creation request can be in. + enum State { + // Invalid. + STATE_UNSPECIFIED = 0; + + // Request is being processed. + RUNNING = 1; + + // The glossary was successfully created. + SUCCEEDED = 2; + + // Failed to create the glossary. + FAILED = 3; + + // Request is in the process of being canceled after caller invoked + // longrunning.Operations.CancelOperation on the request id. + CANCELLING = 4; + + // The glossary creation request was successfully canceled. + CANCELLED = 5; + } + + // The name of the glossary that is being created. + string name = 1; + + // The current state of the glossary creation operation. + State state = 2; + + // The time when the operation was submitted to the server. + google.protobuf.Timestamp submit_time = 3; +} + +// Stored in the [google.longrunning.Operation.metadata][google.longrunning.Operation.metadata] field returned by +// DeleteGlossary. +message DeleteGlossaryMetadata { + // Enumerates the possible states that the creation request can be in. + enum State { + // Invalid. + STATE_UNSPECIFIED = 0; + + // Request is being processed. + RUNNING = 1; + + // The glossary was successfully deleted. + SUCCEEDED = 2; + + // Failed to delete the glossary. + FAILED = 3; + + // Request is in the process of being canceled after caller invoked + // longrunning.Operations.CancelOperation on the request id. + CANCELLING = 4; + + // The glossary deletion request was successfully canceled. + CANCELLED = 5; + } + + // The name of the glossary that is being deleted. + string name = 1; + + // The current state of the glossary deletion operation. + State state = 2; + + // The time when the operation was submitted to the server. + google.protobuf.Timestamp submit_time = 3; +} + +// Stored in the [google.longrunning.Operation.response][google.longrunning.Operation.response] field returned by +// DeleteGlossary. +message DeleteGlossaryResponse { + // The name of the deleted glossary. + string name = 1; + + // The time when the operation was submitted to the server. + google.protobuf.Timestamp submit_time = 2; + + // The time when the glossary deletion is finished and + // [google.longrunning.Operation.done][google.longrunning.Operation.done] is set to true. + google.protobuf.Timestamp end_time = 3; +} diff --git a/typescript/test/testdata/translate/package.json.baseline b/typescript/test/testdata/translate/package.json.baseline new file mode 100644 index 000000000..9b16c43d2 --- /dev/null +++ b/typescript/test/testdata/translate/package.json.baseline @@ -0,0 +1,34 @@ +{ + "repository": "googleapis/nodejs-translation", + "name": "translation", + "version": "0.1.0", + "author": "Google LLC", + "description": "Translation client for Node.js", + "main": "build/src/index.js", + "files": [ + "build/src", + "build/protos" + ], + "dependencies": { + "google-gax": "^1.7.5" + }, + "devDependencies": { + "@types/mocha": "^5.2.5", + "gts": "^0.9.0", + "mocha": "^6.0.0", + "typescript": "~3.5.3" + }, + "scripts": { + "lint": "gts check", + "clean": "gts clean", + "compile": "tsc -p . && cp -r protos build/", + "compile-protos": "compileProtos src", + "fix": "gts fix", + "prepare": "npm run compile-protos && npm run compile", + "test": "mocha build/test" + }, + "license": "Apache-2.0", + "engines": { + "node": ">=8.13.0" + } +} diff --git a/typescript/test/testdata/translate/proto.list.baseline b/typescript/test/testdata/translate/proto.list.baseline new file mode 100644 index 000000000..0aece7694 --- /dev/null +++ b/typescript/test/testdata/translate/proto.list.baseline @@ -0,0 +1,14 @@ +google/api/http.proto +google/protobuf/descriptor.proto +google/api/annotations.proto +google/api/client.proto +google/api/field_behavior.proto +google/api/resource.proto +google/protobuf/any.proto +google/protobuf/duration.proto +google/protobuf/empty.proto +google/rpc/status.proto +google/longrunning/operations.proto +google/protobuf/timestamp.proto +google/cloud/translate/v3beta1/translation_service.proto +google/cloud/common_resources.proto diff --git a/typescript/test/testdata/translate/src/index.ts.baseline b/typescript/test/testdata/translate/src/index.ts.baseline new file mode 100644 index 000000000..2f98e1dd8 --- /dev/null +++ b/typescript/test/testdata/translate/src/index.ts.baseline @@ -0,0 +1,22 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ** This file is automatically generated by gapic-generator-typescript. ** +// ** https://github.com/googleapis/gapic-generator-typescript ** +// ** All changes to this file may be overwritten. ** + +import * as v3beta1 from './v3beta1'; +export {v3beta1}; +const TranslationServiceClient = v3beta1.TranslationServiceClient; +export {TranslationServiceClient}; diff --git a/typescript/test/testdata/translate/src/v3beta1/index.ts.baseline b/typescript/test/testdata/translate/src/v3beta1/index.ts.baseline new file mode 100644 index 000000000..07f3c18ec --- /dev/null +++ b/typescript/test/testdata/translate/src/v3beta1/index.ts.baseline @@ -0,0 +1,19 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ** This file is automatically generated by gapic-generator-typescript. ** +// ** https://github.com/googleapis/gapic-generator-typescript ** +// ** All changes to this file may be overwritten. ** + +export {TranslationServiceClient} from './translation_service_client'; diff --git a/typescript/test/testdata/translate/src/v3beta1/translation_service_client.ts.baseline b/typescript/test/testdata/translate/src/v3beta1/translation_service_client.ts.baseline new file mode 100644 index 000000000..7096ff408 --- /dev/null +++ b/typescript/test/testdata/translate/src/v3beta1/translation_service_client.ts.baseline @@ -0,0 +1,665 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ** This file is automatically generated by gapic-generator-typescript. ** +// ** https://github.com/googleapis/gapic-generator-typescript ** +// ** All changes to this file may be overwritten. ** + +import * as gax from 'google-gax'; +import * as path from 'path'; + +import * as protosTypes from '../../protos/protos'; +import * as gapicConfig from './translation_service_client_config.json'; + +const version = require('../../../package.json').version; + +export interface ClientOptions extends gax.GrpcClientOptions, + gax.GoogleAuthOptions, + gax.ClientStubOptions { + libName?: string; + libVersion?: string; + clientConfig?: gax.ClientConfig; + fallback?: boolean; + apiEndpoint?: string; +} + +interface Descriptors { + page: {[name: string]: gax.PageDescriptor}; + stream: {[name: string]: gax.StreamDescriptor}; + longrunning: {[name: string]: gax.LongrunningDescriptor}; +} + +export interface Callback< + ResponseObject, NextRequestObject, RawResponseObject> { + (err: Error|null|undefined, value?: ResponseObject|null, + nextRequest?: NextRequestObject, rawResponse?: RawResponseObject): void; +} + +export interface Operation extends gax.Operation { + promise(): Promise<[ResultType, MetadataType, protosTypes.google.longrunning.IOperation]>; +} + + +export interface PaginationCallback< + RequestObject, ResponseObject, ResponseType> { + (err: Error|null, values?: ResponseType[], nextPageRequest?: RequestObject, + rawResponse?: ResponseObject): void; +} + +export interface PaginationResponse< + RequestObject, ResponseObject, ResponseType> { + values?: ResponseType[]; + nextPageRequest?: RequestObject; + rawResponse?: ResponseObject; +} + +export class TranslationServiceClient { + /* + Provides natural language translation operations. + */ + private _descriptors: Descriptors = {page: {}, stream: {}, longrunning: {}}; + private _innerApiCalls: {[name: string]: Function}; + private _pathTemplates: {[name: string]: gax.PathTemplate}; + auth: gax.GoogleAuth; + + /** + * Construct an instance of TranslationServiceClient. + * + * @param {object} [options] - The configuration object. See the subsequent + * parameters for more details. + * @param {object} [options.credentials] - Credentials object. + * @param {string} [options.credentials.client_email] + * @param {string} [options.credentials.private_key] + * @param {string} [options.email] - Account email address. Required when + * using a .pem or .p12 keyFilename. + * @param {string} [options.keyFilename] - Full path to the a .json, .pem, or + * .p12 key downloaded from the Google Developers Console. If you provide + * a path to a JSON file, the projectId option below is not necessary. + * NOTE: .pem and .p12 require you to specify options.email as well. + * @param {number} [options.port] - The port on which to connect to + * the remote host. + * @param {string} [options.projectId] - The project ID from the Google + * Developer's Console, e.g. 'grape-spaceship-123'. We will also check + * the environment variable GCLOUD_PROJECT for your project ID. If your + * app is running in an environment which supports + * {@@link + * https://developers.google.com/identity/protocols/application-default-credentials + * Application Default Credentials}, your project ID will be detected + * automatically. + * @param {function} [options.promise] - Custom promise module to use instead + * of native Promises. + * @param {string} [options.apiEndpoint] - The domain name of the + * API remote host. + */ + + constructor(opts?: ClientOptions) { + // Ensure that options include the service address and port. + const staticMembers = this.constructor as typeof TranslationServiceClient; + const servicePath = opts && opts.servicePath ? + opts.servicePath : + ((opts && opts.apiEndpoint) ? opts.apiEndpoint : + staticMembers.servicePath); + const port = opts && opts.port ? opts.port : staticMembers.port; + + if (!opts) { + opts = {servicePath, port}; + } + opts.servicePath = opts.servicePath || servicePath; + opts.port = opts.port || port; + opts.clientConfig = opts.clientConfig || {}; + + const isBrowser = (typeof window !== 'undefined'); + if (isBrowser){ + opts.fallback = true; + } + // If we are in browser, we are already using fallback because of the + // "browser" field in package.json. + // But if we were explicitly requested to use fallback, let's do it now. + const gaxModule = !isBrowser && opts.fallback ? gax.fallback : gax; + + // Create a `gaxGrpc` object, with any grpc-specific options + // sent to the client. + opts.scopes = (this.constructor as typeof TranslationServiceClient).scopes; + const gaxGrpc = new gaxModule.GrpcClient(opts); + + // Save the auth object to the client, for use by other methods. + this.auth = (gaxGrpc.auth as gax.GoogleAuth); + + // Determine the client header string. + const clientHeader = [ + `gl-node/${process.version}`, + `grpc/${gaxGrpc.grpcVersion}`, + `gax/${gaxModule.version}`, + `gapic/${version}`, + `gl-web/${gaxModule.version}` + ]; + if (opts.libName && opts.libVersion) { + clientHeader.push(`${opts.libName}/${opts.libVersion}`); + } + // Load the applicable protos. + // For Node.js, pass the path to JSON proto file. + // For browsers, pass the JSON content. + + const nodejsProtoPath = path.join(__dirname, '..', '..', 'protos', 'protos.json'); + const protos = gaxGrpc.loadProto( + opts.fallback ? + require("../../protos/protos.json") : + nodejsProtoPath + ); + this._pathTemplates = { + locationPathTemplate: new gaxModule.PathTemplate( + 'projects/{project}/locations/{location}' + ), + glossaryPathTemplate: new gaxModule.PathTemplate( + 'projects/{project}/locations/{location}/glossaries/{glossary}' + ), + }; + + // Some of the methods on this service return "paged" results, + // (e.g. 50 results at a time, with tokens to get subsequent + // pages). Denote the keys used for pagination and results. + this._descriptors.page = { + listGlossaries: + new gaxModule.PageDescriptor('pageToken', 'nextPageToken', 'glossaries') + }; + // This API contains "long-running operations", which return a + // an Operation object that allows for tracking of the operation, + // rather than holding a request open. + const protoFilesRoot = opts.fallback? + gaxModule.protobuf.Root.fromJSON(require("../../protos/protos.json")) : + gaxModule.protobuf.loadSync(nodejsProtoPath); + + const operationsClient = gaxModule.lro({ + auth: this.auth, + grpc: 'grpc' in gaxGrpc ? gaxGrpc.grpc : undefined + }).operationsClient(opts); + const batchTranslateTextResponse = protoFilesRoot.lookup( + 'BatchTranslateResponse') as gax.protobuf.Type; + const batchTranslateTextMetadata = protoFilesRoot.lookup( + 'BatchTranslateMetadata') as gax.protobuf.Type; + const createGlossaryResponse = protoFilesRoot.lookup( + 'Glossary') as gax.protobuf.Type; + const createGlossaryMetadata = protoFilesRoot.lookup( + 'CreateGlossaryMetadata') as gax.protobuf.Type; + const deleteGlossaryResponse = protoFilesRoot.lookup( + 'DeleteGlossaryResponse') as gax.protobuf.Type; + const deleteGlossaryMetadata = protoFilesRoot.lookup( + 'DeleteGlossaryMetadata') as gax.protobuf.Type; + + this._descriptors.longrunning = { + batchTranslateText: new gaxModule.LongrunningDescriptor( + operationsClient, + batchTranslateTextResponse.decode.bind(batchTranslateTextResponse), + batchTranslateTextMetadata.decode.bind(batchTranslateTextMetadata)), + createGlossary: new gaxModule.LongrunningDescriptor( + operationsClient, + createGlossaryResponse.decode.bind(createGlossaryResponse), + createGlossaryMetadata.decode.bind(createGlossaryMetadata)), + deleteGlossary: new gaxModule.LongrunningDescriptor( + operationsClient, + deleteGlossaryResponse.decode.bind(deleteGlossaryResponse), + deleteGlossaryMetadata.decode.bind(deleteGlossaryMetadata)) + }; + + // Put together the default options sent with requests. + const defaults = gaxGrpc.constructSettings( + 'google.cloud.translation.v3beta1.TranslationService', gapicConfig as gax.ClientConfig, + opts.clientConfig || {}, {'x-goog-api-client': clientHeader.join(' ')}); + + // Set up a dictionary of "inner API calls"; the core implementation + // of calling the API is handled in `google-gax`, with this code + // merely providing the destination and request information. + this._innerApiCalls = {}; + + // Put together the "service stub" for + // google.showcase.v1alpha2.Echo. + const translationServiceStub = gaxGrpc.createStub( + opts.fallback ? + // @ts-ignore Do not check types for loaded protos + protos.lookupService('google.cloud.translation.v3beta1.TranslationService') : + // @ts-ignore Do not check types for loaded protos + protos.google.cloud.translation.v3beta1.TranslationService, + opts) as Promise<{[method: string]: Function}>; + + const translationServiceStubMethods = + ['translateText', 'detectLanguage', 'getSupportedLanguages', 'batchTranslateText', 'createGlossary', 'listGlossaries', 'getGlossary', 'deleteGlossary']; + + for (const methodName of translationServiceStubMethods) { + const innerCallPromise = translationServiceStub.then( + (stub: {[method: string]: Function}) => (...args: Array<{}>) => { + return stub[methodName].apply(stub, args); + }, + (err: Error|null|undefined) => () => { + throw err; + }); + + this._innerApiCalls[methodName] = gax.createApiCall( + innerCallPromise, + defaults[methodName], + this._descriptors.page[methodName] || + this._descriptors.stream[methodName] || + this._descriptors.longrunning[methodName] + ); + } + } + /** + * The DNS address for this API service. + */ + static get servicePath() { + return 'translate.googleapis.com'; + } + /** + * The DNS address for this API service - same as servicePath(), + * exists for compatibility reasons. + */ + static get apiEndpoint() { + return 'translate.googleapis.com'; + } + + /** + * The port for this API service. + */ + static get port() { + return 443; + } + + /** + * The scopes needed to make gRPC calls for every method defined + * in this service. + */ + static get scopes() { + return [ + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/cloud-translation' + ]; + } + + /** + * Return the project ID used by this class. + * @param {function(Error, string)} callback - the callback to + * be called with the current project Id. + */ + getProjectId(): Promise; + getProjectId(callback: Callback): void; + getProjectId(callback?: Callback): + Promise|void { + if (callback) { + this.auth.getProjectId(callback); + return; + } + return this.auth.getProjectId(); + } + + // ------------------- + // -- Service calls -- + // ------------------- + /* + Translates input text and returns translated text. + */ + translateText( + request: protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest, + options?: gax.CallOptions): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.ITranslateTextResponse, + protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest|undefined, {}|undefined + ]>; + translateText( + request: protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest, + options: gax.CallOptions, + callback: Callback< + protosTypes.google.cloud.translation.v3beta1.ITranslateTextResponse, + protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest|undefined, + {}|undefined>): void; + translateText( + request: protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest, + optionsOrCallback?: gax.CallOptions|Callback< + protosTypes.google.cloud.translation.v3beta1.ITranslateTextResponse, + protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest|undefined, {}|undefined>, + callback?: Callback< + protosTypes.google.cloud.translation.v3beta1.ITranslateTextResponse, + protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest|undefined, + {}|undefined>): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.ITranslateTextResponse, + protosTypes.google.cloud.translation.v3beta1.ITranslateTextRequest|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.translateText(request, options, callback); + } + /* + Detects the language of text within a request. + */ + detectLanguage( + request: protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest, + options?: gax.CallOptions): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageResponse, + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest|undefined, {}|undefined + ]>; + detectLanguage( + request: protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest, + options: gax.CallOptions, + callback: Callback< + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageResponse, + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest|undefined, + {}|undefined>): void; + detectLanguage( + request: protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest, + optionsOrCallback?: gax.CallOptions|Callback< + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageResponse, + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest|undefined, {}|undefined>, + callback?: Callback< + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageResponse, + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest|undefined, + {}|undefined>): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageResponse, + protosTypes.google.cloud.translation.v3beta1.IDetectLanguageRequest|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.detectLanguage(request, options, callback); + } + /* + Returns a list of supported languages for translation. + */ + getSupportedLanguages( + request: protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest, + options?: gax.CallOptions): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.ISupportedLanguages, + protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest|undefined, {}|undefined + ]>; + getSupportedLanguages( + request: protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest, + options: gax.CallOptions, + callback: Callback< + protosTypes.google.cloud.translation.v3beta1.ISupportedLanguages, + protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest|undefined, + {}|undefined>): void; + getSupportedLanguages( + request: protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest, + optionsOrCallback?: gax.CallOptions|Callback< + protosTypes.google.cloud.translation.v3beta1.ISupportedLanguages, + protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest|undefined, {}|undefined>, + callback?: Callback< + protosTypes.google.cloud.translation.v3beta1.ISupportedLanguages, + protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest|undefined, + {}|undefined>): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.ISupportedLanguages, + protosTypes.google.cloud.translation.v3beta1.IGetSupportedLanguagesRequest|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.getSupportedLanguages(request, options, callback); + } + /* + Gets a glossary. Returns NOT_FOUND, if the glossary doesn't + exist. + */ + getGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest, + options?: gax.CallOptions): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IGlossary, + protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest|undefined, {}|undefined + ]>; + getGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest, + options: gax.CallOptions, + callback: Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary, + protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest|undefined, + {}|undefined>): void; + getGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest, + optionsOrCallback?: gax.CallOptions|Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary, + protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest|undefined, {}|undefined>, + callback?: Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary, + protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest|undefined, + {}|undefined>): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IGlossary, + protosTypes.google.cloud.translation.v3beta1.IGetGlossaryRequest|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.getGlossary(request, options, callback); + } + + /* + Translates a large volume of text in asynchronous batch mode. + This function provides real-time output as the inputs are being processed. + If caller cancels a request, the partial results (for an input file, it's + all or nothing) may still be available on the specified output location. + + This call returns immediately and you can + use google.longrunning.Operation.name to poll the status of the call. + */ + batchTranslateText( + request: protosTypes.google.cloud.translation.v3beta1.IBatchTranslateTextRequest, + options?: gax.CallOptions): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>; + batchTranslateText( + request: protosTypes.google.cloud.translation.v3beta1.IBatchTranslateTextRequest, + options: gax.CallOptions, + callback: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): void; + batchTranslateText( + request: protosTypes.google.cloud.translation.v3beta1.IBatchTranslateTextRequest, + optionsOrCallback?: gax.CallOptions|Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined>, + callback?: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.batchTranslateText(request, options, callback); + } + /* + Creates a glossary and returns the long-running operation. Returns + NOT_FOUND, if the project doesn't exist. + */ + createGlossary( + request: protosTypes.google.cloud.translation.v3beta1.ICreateGlossaryRequest, + options?: gax.CallOptions): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>; + createGlossary( + request: protosTypes.google.cloud.translation.v3beta1.ICreateGlossaryRequest, + options: gax.CallOptions, + callback: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): void; + createGlossary( + request: protosTypes.google.cloud.translation.v3beta1.ICreateGlossaryRequest, + optionsOrCallback?: gax.CallOptions|Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined>, + callback?: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.createGlossary(request, options, callback); + } + /* + Deletes a glossary, or cancels glossary construction + if the glossary isn't created yet. + Returns NOT_FOUND, if the glossary doesn't exist. + */ + deleteGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IDeleteGlossaryRequest, + options?: gax.CallOptions): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>; + deleteGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IDeleteGlossaryRequest, + options: gax.CallOptions, + callback: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): void; + deleteGlossary( + request: protosTypes.google.cloud.translation.v3beta1.IDeleteGlossaryRequest, + optionsOrCallback?: gax.CallOptions|Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined>, + callback?: Callback< + Operation, + protosTypes.google.longrunning.IOperation|undefined, + {}|undefined>): + Promise<[ + Operation, + protosTypes.google.longrunning.IOperation|undefined, {}|undefined + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.deleteGlossary(request, options, callback); + } + /* + Lists glossaries in a project. Returns NOT_FOUND, if the project doesn't + exist. + */ + listGlossaries( + request: protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest, + options?: gax.CallOptions): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IGlossary[], + protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest|null, + protosTypes.google.cloud.translation.v3beta1.IListGlossariesResponse + ]>; + listGlossaries( + request: protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest, + options: gax.CallOptions, + callback: Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary[], + protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest|null, + protosTypes.google.cloud.translation.v3beta1.IListGlossariesResponse>): void; + listGlossaries( + request: protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest, + optionsOrCallback?: gax.CallOptions|Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary[], + protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest|null, + protosTypes.google.cloud.translation.v3beta1.IListGlossariesResponse>, + callback?: Callback< + protosTypes.google.cloud.translation.v3beta1.IGlossary[], + protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest|null, + protosTypes.google.cloud.translation.v3beta1.IListGlossariesResponse>): + Promise<[ + protosTypes.google.cloud.translation.v3beta1.IGlossary[], + protosTypes.google.cloud.translation.v3beta1.IListGlossariesRequest|null, + protosTypes.google.cloud.translation.v3beta1.IListGlossariesResponse + ]>|void { + request = request || {}; + let options = optionsOrCallback; + if (typeof options === 'function' && callback === undefined) { + callback = options; + options = {}; + } + options = options || {}; + return this._innerApiCalls.listGlossaries(request, options, callback); + } + // -------------------- + // -- Path templates -- + // -------------------- + locationPath(project:string,location:string){ + return this._pathTemplates.locationPathTemplate.render({ + project: project, + location: location, + }); + } + matchProjectFromLocationName(locationName: string){ + return this._pathTemplates.locationPathTemplate.match(locationName).project; + } + matchLocationFromLocationName(locationName: string){ + return this._pathTemplates.locationPathTemplate.match(locationName).location; + } + glossaryPath(project:string,location:string,glossary:string){ + return this._pathTemplates.glossaryPathTemplate.render({ + project: project, + location: location, + glossary: glossary, + }); + } + matchProjectFromGlossaryName(glossaryName: string){ + return this._pathTemplates.glossaryPathTemplate.match(glossaryName).project; + } + matchLocationFromGlossaryName(glossaryName: string){ + return this._pathTemplates.glossaryPathTemplate.match(glossaryName).location; + } + matchGlossaryFromGlossaryName(glossaryName: string){ + return this._pathTemplates.glossaryPathTemplate.match(glossaryName).glossary; + } +} diff --git a/typescript/test/testdata/translate/src/v3beta1/translation_service_client_config.json.baseline b/typescript/test/testdata/translate/src/v3beta1/translation_service_client_config.json.baseline new file mode 100644 index 000000000..1469f08a0 --- /dev/null +++ b/typescript/test/testdata/translate/src/v3beta1/translation_service_client_config.json.baseline @@ -0,0 +1,58 @@ +{ + "interfaces": { + "google.cloud.translation.v3beta1.TranslationService": { + "retry_codes": { + "non_idempotent": [], + "idempotent": [ + "DEADLINE_EXCEEDED", + "UNAVAILABLE" + ] + }, + "retry_params": { + "default": { + "initial_retry_delay_millis": 100, + "retry_delay_multiplier": 1.3, + "max_retry_delay_millis": 60000, + "initial_rpc_timeout_millis": 20000, + "rpc_timeout_multiplier": 1, + "max_rpc_timeout_millis": 20000, + "total_timeout_millis": 600000 + } + }, + "methods": { + "TranslateText": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "DetectLanguage": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "GetSupportedLanguages": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "BatchTranslateText": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "CreateGlossary": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "ListGlossaries": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "GetGlossary": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + }, + "DeleteGlossary": { + "retry_codes_name": "non_idempotent", + "retry_params_name": "default" + } + } + } + } +} diff --git a/typescript/test/testdata/translate/src/v3beta1/translation_service_proto_list.json.baseline b/typescript/test/testdata/translate/src/v3beta1/translation_service_proto_list.json.baseline new file mode 100644 index 000000000..47a656634 --- /dev/null +++ b/typescript/test/testdata/translate/src/v3beta1/translation_service_proto_list.json.baseline @@ -0,0 +1,4 @@ +[ + "../../protos/google/cloud/translate/v3beta1/translation_service.proto", + "../../protos/google/cloud/common_resources.proto" +] diff --git a/typescript/test/testdata/translate/test/gapic-translation_service-v3beta1.ts.baseline b/typescript/test/testdata/translate/test/gapic-translation_service-v3beta1.ts.baseline new file mode 100644 index 000000000..090baa975 --- /dev/null +++ b/typescript/test/testdata/translate/test/gapic-translation_service-v3beta1.ts.baseline @@ -0,0 +1,461 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ** This file is automatically generated by gapic-generator-typescript. ** +// ** https://github.com/googleapis/gapic-generator-typescript ** +// ** All changes to this file may be overwritten. ** + +'use strict'; + +const assert = require('assert'); +const translationserviceModule = require('../src'); + + +const FAKE_STATUS_CODE = 1; +class FakeError{ + code: number; + constructor(n: number){ + this.code = n; + } +} +const error = new FakeError(FAKE_STATUS_CODE); +export interface Callback { + (err: FakeError|null, response?: {} | null): {}; +} + +export class Operation{ + constructor(){}; + promise() {}; +} + +function mockSimpleGrpcMethod(expectedRequest: {}, response: {} | null, error: FakeError | null) { + return (actualRequest: {}, options: {}, callback: Callback) => { + assert.deepStrictEqual(actualRequest, expectedRequest); + if (error) { + callback(error); + } else if (response) { + callback(null, response); + } else { + callback(null); + } + }; +} +function mockLongRunningGrpcMethod(expectedRequest: {}, response: {} | null, error?: {} | null) { + return (request: {}) => { + assert.deepStrictEqual(request, expectedRequest); + const mockOperation = { + promise: function() { + return new Promise((resolve, reject) => { + if (error) { + reject(error); + } + else { + resolve([response]); + } + }); + } + }; + return Promise.resolve([mockOperation]); + }; +} +describe('TranslationServiceClient', () => { + it('has servicePath', () => { + const servicePath = translationserviceModule.v3beta1.TranslationServiceClient.servicePath; + assert(servicePath); + }); + it('has apiEndpoint', () => { + const apiEndpoint = translationserviceModule.v3beta1.TranslationServiceClient.apiEndpoint; + assert(apiEndpoint); + }); + it('has port', () => { + const port = translationserviceModule.v3beta1.TranslationServiceClient.port; + assert(port); + assert(typeof port === 'number'); + }); + it('should create a client with no option', () => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient(); + assert(client); + }); + it('should create a client with gRPC option', () => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + fallback: true, + }); + assert(client); + }); + describe('translateText', () => { + it('invokes translateText without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.translateText = mockSimpleGrpcMethod( + request, + expectedResponse, + null + ); + client.translateText(request, (err: {}, response: {}) => { + assert.ifError(err); + assert.deepStrictEqual(response, expectedResponse); + done(); + }) + }); + + it('invokes translateText with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.translateText = mockSimpleGrpcMethod( + request, + null, + error + ); + client.translateText(request, (err: FakeError, response: {}) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + assert(typeof response === 'undefined'); + done(); + }) + }); + }); + describe('detectLanguage', () => { + it('invokes detectLanguage without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.detectLanguage = mockSimpleGrpcMethod( + request, + expectedResponse, + null + ); + client.detectLanguage(request, (err: {}, response: {}) => { + assert.ifError(err); + assert.deepStrictEqual(response, expectedResponse); + done(); + }) + }); + + it('invokes detectLanguage with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.detectLanguage = mockSimpleGrpcMethod( + request, + null, + error + ); + client.detectLanguage(request, (err: FakeError, response: {}) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + assert(typeof response === 'undefined'); + done(); + }) + }); + }); + describe('getSupportedLanguages', () => { + it('invokes getSupportedLanguages without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.getSupportedLanguages = mockSimpleGrpcMethod( + request, + expectedResponse, + null + ); + client.getSupportedLanguages(request, (err: {}, response: {}) => { + assert.ifError(err); + assert.deepStrictEqual(response, expectedResponse); + done(); + }) + }); + + it('invokes getSupportedLanguages with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.getSupportedLanguages = mockSimpleGrpcMethod( + request, + null, + error + ); + client.getSupportedLanguages(request, (err: FakeError, response: {}) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + assert(typeof response === 'undefined'); + done(); + }) + }); + }); + describe('getGlossary', () => { + it('invokes getGlossary without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.getGlossary = mockSimpleGrpcMethod( + request, + expectedResponse, + null + ); + client.getGlossary(request, (err: {}, response: {}) => { + assert.ifError(err); + assert.deepStrictEqual(response, expectedResponse); + done(); + }) + }); + + it('invokes getGlossary with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.getGlossary = mockSimpleGrpcMethod( + request, + null, + error + ); + client.getGlossary(request, (err: FakeError, response: {}) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + assert(typeof response === 'undefined'); + done(); + }) + }); + }); + describe('batchTranslateText', () => { + it('invokes batchTranslateText without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.batchTranslateText = mockLongRunningGrpcMethod( + request, + expectedResponse + ); + client.batchTranslateText(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then((responses: [Operation]) => { + assert.deepStrictEqual(responses[0], expectedResponse); + done(); + }).catch((err: {}) => { + done(err); + }); + }); + + it('invokes batchTranslateText with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.batchTranslateText = mockLongRunningGrpcMethod( + request, + null, + error + ); + client.batchTranslateText(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then(() => { + assert.fail(); + }).catch((err: FakeError) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + done(); + }); + }); + }); + describe('createGlossary', () => { + it('invokes createGlossary without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.createGlossary = mockLongRunningGrpcMethod( + request, + expectedResponse + ); + client.createGlossary(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then((responses: [Operation]) => { + assert.deepStrictEqual(responses[0], expectedResponse); + done(); + }).catch((err: {}) => { + done(err); + }); + }); + + it('invokes createGlossary with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.createGlossary = mockLongRunningGrpcMethod( + request, + null, + error + ); + client.createGlossary(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then(() => { + assert.fail(); + }).catch((err: FakeError) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + done(); + }); + }); + }); + describe('deleteGlossary', () => { + it('invokes deleteGlossary without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.deleteGlossary = mockLongRunningGrpcMethod( + request, + expectedResponse + ); + client.deleteGlossary(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then((responses: [Operation]) => { + assert.deepStrictEqual(responses[0], expectedResponse); + done(); + }).catch((err: {}) => { + done(err); + }); + }); + + it('invokes deleteGlossary with error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock gRPC layer + client._innerApiCalls.deleteGlossary = mockLongRunningGrpcMethod( + request, + null, + error + ); + client.deleteGlossary(request).then((responses: [Operation]) => { + const operation = responses[0]; + return operation? operation.promise() : {}; + }).then(() => { + assert.fail(); + }).catch((err: FakeError) => { + assert(err instanceof FakeError); + assert.strictEqual(err.code, FAKE_STATUS_CODE); + done(); + }); + }); + }); + describe('listGlossaries', () => { + it('invokes listGlossaries without error', done => { + const client = new translationserviceModule.v3beta1.TranslationServiceClient({ + credentials: {client_email: 'bogus', private_key: 'bogus'}, + projectId: 'bogus', + }); + // Mock request + const request = {}; + // Mock response + const expectedResponse = {}; + // Mock Grpc layer + client._innerApiCalls.listGlossaries = (actualRequest: {}, options: {}, callback: Callback) => { + assert.deepStrictEqual(actualRequest, request); + callback(null, expectedResponse); + }; + client.listGlossaries(request, (err: FakeError, response: {}) => { + assert.ifError(err); + assert.deepStrictEqual(response, expectedResponse); + done(); + }); + }); + }); +}); diff --git a/typescript/test/testdata/translate/tsconfig.json.baseline b/typescript/test/testdata/translate/tsconfig.json.baseline new file mode 100644 index 000000000..653c21079 --- /dev/null +++ b/typescript/test/testdata/translate/tsconfig.json.baseline @@ -0,0 +1,18 @@ +{ + "extends": "./node_modules/gts/tsconfig-google.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build", + "resolveJsonModule": true, + "lib": [ + "es2016", + "dom" + ] + }, + "include": [ + "src/*.ts", + "src/**/*.ts", + "test/*.ts", + "test/**/*.ts" + ] +} diff --git a/typescript/test/testdata/translate/tslint.json.baseline b/typescript/test/testdata/translate/tslint.json.baseline new file mode 100644 index 000000000..b3bfaf592 --- /dev/null +++ b/typescript/test/testdata/translate/tslint.json.baseline @@ -0,0 +1,6 @@ +{ + "extends": "gts/tslint.json", + "rules": { + "ban-ts-ignore": false + } +} diff --git a/typescript/test/unit/resource.ts b/typescript/test/unit/resource.ts new file mode 100644 index 000000000..95b11b138 --- /dev/null +++ b/typescript/test/unit/resource.ts @@ -0,0 +1,94 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as assert from 'assert'; +import { execSync } from 'child_process'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as rimraf from 'rimraf'; +import { equalToBaseline } from '../util'; + +const cwd = process.cwd(); + +const OUTPUT_DIR = path.join(cwd, '.test-out-translate'); +const GOOGLE_GAX_PROTOS_DIR = path.join( + cwd, + 'node_modules', + 'google-gax', + 'protos' +); +const PROTOS_DIR = path.join(cwd, 'build', 'test', 'protos'); +const TRANSLATE_PROTO_FILE = path.join( + PROTOS_DIR, + 'google', + 'cloud', + 'translate', + 'v3beta1', + 'translation_service.proto ' +); + +const COMMON_PROTO_FILE = path.join( + PROTOS_DIR, + 'google', + 'cloud', + 'common_resources.proto' +); + +const BASELINE_DIR = path.join( + __dirname, + '..', + '..', + '..', + 'typescript', + 'test', + 'testdata' +); + +const BASELINE_DIR_KM = path.join(BASELINE_DIR, 'translate'); +const SRCDIR = path.join(cwd, 'build', 'src'); +const CLI = path.join(SRCDIR, 'cli.js'); +const PLUGIN = path.join(SRCDIR, 'protoc-gen-typescript_gapic'); + +describe('LibraryWithCommonResourceGenerateTest', () => { + describe('Generate Client library', () => { + it('Generated client library with common resource should have same output with baseline.', function() { + this.timeout(10000); + if (fs.existsSync(OUTPUT_DIR)) { + rimraf.sync(OUTPUT_DIR); + } + fs.mkdirSync(OUTPUT_DIR); + + if (fs.existsSync(PLUGIN)) { + rimraf.sync(PLUGIN); + } + fs.copyFileSync(CLI, PLUGIN); + process.env['PATH'] = SRCDIR + path.delimiter + process.env['PATH']; + + try { + execSync(`chmod +x ${PLUGIN}`); + } catch (err) { + console.warn(`Failed to chmod +x ${PLUGIN}: ${err}. Ignoring...`); + } + + execSync( + `protoc --typescript_gapic_out=${OUTPUT_DIR} ` + + `-I${GOOGLE_GAX_PROTOS_DIR} ` + + `-I${PROTOS_DIR} ` + + TRANSLATE_PROTO_FILE + + COMMON_PROTO_FILE + ); + assert(equalToBaseline(OUTPUT_DIR, BASELINE_DIR_KM)); + }); + }); +});