Project structure question
felixmosh opened this issue · 2 comments
Hi,
I've some time to invest in order to optimize this lib so it will be more suitable for production use (#83 #87 #84)
But I'm not getting the structure of it.
I did understood that it gets generated from googles protobuf defs.
- What is the relation between
build/src
folder and thebuild/protos/protos.js
file? - Do we need
build/src
on production usage? (isgoogle-ads-api
uses it?)
Any help will be really appreciated.
The problem is how googleapis builds the protos. It builds it into a single monolithic proto, which is then built into a single Typescript file.
To avoid this, I recommend:
- Building the protos with
protobuf-ts
- Running it with
@grpc/grpc-js
- Not using this library at all
Building the protos
Here's a file to checkout the googleapis project and build the protos to a folder:
#!/bin/bash
GOOGLE_APIS_PATH="$1"
OUTPUT_DIR="$2"
if [ ! -e "$GOOGLE_APIS_PATH/.git" ]; then
echo 'Cloning Git repository'
git clone git@github.com:googleapis/googleapis.git "$GOOGLE_APIS_PATH"
fi
cd "$GOOGLE_APIS_PATH"
if [ ! -e "$GOOGLE_APIS_PATH/node_modules/@protobuf-ts/plugin" ]; then
echo 'Installing protocol buffer compiler'
# Install the protoc compiler temporarily in googleapis. We only do this
# if it doesn't look installed to make rerunning this script faster
git checkout . && git clean -f -d
git fetch
git reset --hard origin/master
# Add the plugin needed to build googleApisProtos into Typescript files
yarn init -y
yarn add @protobuf-ts/plugin
fi
yarn protoc --ts_out "$OUTPUT_DIR" --proto_path . \
--ts_opt generate_dependencies,long_type_number \
google/ads/googleads/v11/services/customer_service.proto \
google/ads/googleads/v11/services/conversion_upload_service.proto
Using the protos
These options will be needed for any endpoint:
import { UserRefreshClient } from 'google-auth-library';
import { credentials as gc } from '@grpc/grpc-js';
import { GrpcTransport } from '@protobuf-ts/grpc-transport';
import { RpcOptions } from '@protobuf-ts/runtime-rpc';
const config = { /* ... */ };
/**
* These options include required options from Google Ads API documentation on
* headers:
* https://developers.google.com/google-ads/api/rest/auth#request_headers
*/
export const googleAdsRpcOptions: RpcOptions = {
meta: {
'developer-token': config.developerToken,
'login-customer-id': config.customerId,
},
};
/**
* Creates a GrpcTransport with the signed-in credentials that can be used to
* access the APIs.
*/
export function getGoogleAdsTransport() {
const { refreshToken, clientId, clientSecret } = config;
// Code to create the client and credentials were heavily based on:
//
// - google-ads-node library: https://github.com/Opteo/google-ads-api/blob/v11/src/service.ts#L71
// - GRPC credentials documentation: https://grpc.github.io/grpc/node/grpc.credentials.html
const authClient = new UserRefreshClient(
clientId,
clientSecret,
refreshToken,
);
const credentials = gc.combineChannelCredentials(
gc.createSsl(),
gc.createFromGoogleCredential(authClient),
);
return new GrpcTransport({
// URL was found in https://raw.githubusercontent.com/googleapis/googleapis/master/api-index-v1.json
// Just do a find for "google/ads/googleads" to find the relevant
// configuration
host: 'googleads.googleapis.com',
channelCredentials: credentials,
});
}
Using the APIs
Pass in the transport to the constructor for the client, and pass in the options to
new CustomerServiceClient(getGoogleAdsTransport()).listAccessibleCustomers({}, googleAdsRpcOptions);
Additional notes
Note that the errors.proto
is also huge, so if you only need to use it, you may want to edit it and reduce its size.