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

Project structure question #99

Open
felixmosh opened this issue Jun 13, 2022 · 2 comments
Open

Project structure question #99

felixmosh opened this issue Jun 13, 2022 · 2 comments

Comments

@felixmosh
Copy link

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.

  1. What is the relation between build/src folder and the build/protos/protos.js file?
  2. Do we need build/src on production usage? (is google-ads-api uses it?)

Any help will be really appreciated.

@hsource
Copy link

hsource commented Sep 21, 2022

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:

  1. Building the protos with protobuf-ts
  2. Running it with @grpc/grpc-js
  3. 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 [email protected]: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.

@felixmosh
Copy link
Author

felixmosh commented Oct 13, 2022

Thank you @hsource ,
I think that suggesting to ditch the lib entirely is valid, but in my case it will require much more time to refactor the code since I have a heavy usage of this lib.

Maybe you can somehow incorporate your solution into this lib?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants