Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: respect common resources #81

Merged
merged 15 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions templates/typescript_gapic/src/$version/$service_client.ts.njk
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,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;
Expand Down Expand Up @@ -145,9 +145,9 @@ 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 %}
{%- for template in service.pathTemplates %}
{{ template.type.toCamelCase() }}PathTemplate: new gaxModule.PathTemplate(
'{{ template.pattern }}'
),
Expand Down Expand Up @@ -496,11 +496,11 @@ 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 %}
{%- for template in service.pathTemplates %}
{{ template.type.toLowerCase() }}Path(
{%- set paramJoiner = joiner() %}
{%- for param in template.params %}
Expand Down
57 changes: 55 additions & 2 deletions typescript/src/schema/api.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -83,3 +91,48 @@ export class API {
);
}
}

function getResourceMap(
fd: plugin.google.protobuf.IFileDescriptorProto[]
): ResourceMap {
const resourceMap: ResourceMap = {};
for (const fileDescriptor of fd) {
const messages = fileDescriptor
.messageType!.filter(message => message.name)
xiaozhenliu-gg5 marked this conversation as resolved.
Show resolved Hide resolved
.reduce(
(map, message) => {
map['.' + fileDescriptor.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) {
oneResource.name = arr[arr.length - 1];
xiaozhenliu-gg5 marked this conversation as resolved.
Show resolved Hide resolved
}
}
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;
}
resourceMap[opt.type!] = oneResource;
xiaozhenliu-gg5 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
return resourceMap;
}
56 changes: 30 additions & 26 deletions typescript/src/schema/proto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,22 @@ interface ServiceDescriptorProto
port: number;
oauthScopes: string[];
comments: string;
pathTemplate: ResourceDescriptor[];
pathTemplates: ResourceDescriptor[];
commentsMap: CommentsMap;
retryableCodeMap: RetryableCodeMap;
grpcServiceConfig: plugin.grpc.service_config.ServiceConfig;
}

export interface ResourceDescriptor
extends plugin.google.api.IResourceDescriptor {
name: string;
params: string[];
}

export interface ResourceMap {
[name: string]: ResourceDescriptor;
}

export interface ServicesMap {
[name: string]: ServiceDescriptorProto;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -442,32 +448,28 @@ 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(
'resource does not have a type or resource is not in the map'
xiaozhenliu-gg5 marked this conversation as resolved.
Show resolved Hide resolved
);
continue;
}
const resource = resourceMap[resourceReference.type!.toString()];
if (augmentedService.pathTemplates.includes(resource)) continue;
augmentedService.pathTemplates.push(resource);
}
onePathTemplate.params = params;
}
augmentedService.pathTemplate.push(onePathTemplate);
}
}
}
Expand All @@ -485,7 +487,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 || [];
Expand Down Expand Up @@ -525,7 +528,8 @@ export class Proto {
packageName,
service,
commentsMap,
grpcServiceConfig
grpcServiceConfig,
resourceMap
)
)
.reduce(
Expand Down