@google-cloud/nodejs-common 1.0.4 → 1.1.1-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # NodeJS Common Library
2
2
 
3
- <!--* freshness: { owner: 'lushu' reviewed: '2021-12-02' } *-->
3
+ <!--* freshness: { owner: 'lushu' reviewed: '2022-04-07' } *-->
4
4
 
5
5
  A NodeJs common library for other projects, e.g. [GMP and Google Ads Connector]
6
6
  and [Data Tasks Coordinator]. This library includes:
@@ -11,68 +11,65 @@ and [Data Tasks Coordinator]. This library includes:
11
11
  1. Wrapper for some Google APIs for integration, mainly
12
12
  for [GMP and Google Ads Connector]:
13
13
 
14
- * Google Analytics data import
15
- * Google Analytics measurement protocol
16
- * Campaign Manager offline conversion upload
17
- * Search Ads 360 conversions upload
18
- * Google Ads click conversions upload
19
- * Google Ads customer match upload
20
- * Google Ads conversions scheduled uploads based on Google Sheets
21
- * Measurement Protocol Google Analytics 4
14
+ - Google Analytics data import
15
+ - Google Analytics measurement protocol
16
+ - Campaign Manager offline conversion upload
17
+ - Search Ads 360 conversions upload
18
+ - Google Ads click conversions upload
19
+ - Google Ads customer match upload
20
+ - Google Ads enhanced conversions upload
21
+ - Google Ads conversions scheduled uploads based on Google Sheets
22
+ - Measurement Protocol Google Analytics 4
22
23
 
23
24
  1. Wrapper for some Google APIs for reporting, mainly
24
25
  for [Data Tasks Coordinator]:
25
26
 
26
- * Google Ads reporting
27
- * Campaign Manager reporting
28
- * Search Ads 360 reporting
29
- * Display and Video 360 reporting
30
- * YouTube Data API
31
- * Ads Data Hub querying
27
+ - Google Ads reporting
28
+ - Campaign Manager reporting
29
+ - Search Ads 360 reporting
30
+ - Display and Video 360 reporting
31
+ - YouTube Data API
32
+ - Ads Data Hub querying
32
33
 
33
34
  1. Utilities wrapper class for Google Cloud Products:
34
35
 
35
- * **Firestore Access Object**: Firestore has two modes which are excluded to
36
- each other and can't be changed once selected in a Cloud Project[[2]].
37
- This class, with its two successors offer a unified interface to operate
38
- data objects on either Firestore or Datastore.
36
+ - **Firestore Access Object**: Firestore has two modes which are excluded to
37
+ each other and can't be changed once selected in a Cloud Project[[2]].
38
+ This class, with its two successors offer a unified interface to operate
39
+ data objects on either Firestore or Datastore.
39
40
 
40
- * **AutoMl Tables API**: Offers a unified entry to use this API based on
41
- Google Cloud client library combined with REST requests to service
42
- directly due to some functionalities missed in the client library.
41
+ - **AutoMl Tables API**: Offers a unified entry to use this API based on
42
+ Google Cloud client library combined with REST requests to service
43
+ directly due to some functionalities missed in the client library.
43
44
 
44
- * **Vertex AI API**: Offers a unified entry to use this API based on Google
45
- Cloud client library.
45
+ - **Vertex AI API**: Offers a unified entry to use this API based on Google
46
+ Cloud client library.
46
47
 
47
- * **Pub/Sub Utilities**: Offers utilities functions to create topics and
48
- subscriptions for Pub/Sub, as well as the convenient way to publish a
49
- message.
48
+ - **Pub/Sub Utilities**: Offers utilities functions to create topics and
49
+ subscriptions for Pub/Sub, as well as the convenient way to publish a
50
+ message.
50
51
 
51
- * **Storage Utilities**: Offers functions to manipulate the files on Cloud
52
- Storage. The main functions are:
52
+ - **Storage Utilities**: Offers functions to manipulate the files on Cloud
53
+ Storage. The main functions are:
53
54
 
54
- * Reading a given length (or slightly less) content without breaking a
55
- line;
56
- * Splitting a file into multiple files with the given length (or
57
- slightly less) without breaking a line;
58
- * Merging files into one file.
55
+ - Reading a given length (or slightly less) content without breaking a
56
+ line;
57
+ - Splitting a file into multiple files with the given length (or
58
+ slightly less) without breaking a line;
59
+ - Merging files into one file.
59
60
 
60
- * **Cloud Scheduler Adapter**: A wrapper to pause and resume Cloud Scheduler
61
- jobs.
61
+ - **Cloud Scheduler Adapter**: A wrapper to pause and resume Cloud Scheduler
62
+ jobs.
62
63
 
63
- * **Cloud Functions Adapter**: Cloud Functions have different parameters in
64
- different environments, e.g. Node6 vs Node8[[1]]. This utility file offers
65
- an adapter to wrap a Node8 Cloud Functions into Node6 and Node8 compatible
66
- functions.
64
+ - **Cloud Functions Adapter**: Cloud Functions have different parameters in
65
+ different environments, e.g. Node6 vs Node8[[1]]. This utility file offers
66
+ an adapter to wrap a Node8 Cloud Functions into Node6 and Node8 compatible
67
+ functions.
67
68
 
68
69
  1. A share library for [Bash] to facilitate installation tasks.
69
70
 
70
- [GMP and Google Ads Connector]:https://github.com/GoogleCloudPlatform/cloud-for-marketing/tree/master/marketing-analytics/activation/gmp-googleads-connector
71
-
72
- [Data Tasks Coordinator]:https://github.com/GoogleCloudPlatform/cloud-for-marketing/tree/master/marketing-analytics/activation/data-tasks-coordinator
73
-
74
- [1]:https://cloud.google.com/functions/docs/writing/background#functions-writing-background-hello-pubsub-node8-10
75
-
76
- [2]:https://cloud.google.com/datastore/docs/concepts/overview#comparison_with_traditional_databases
77
-
78
- [Bash]:https://www.gnu.org/software/bash/
71
+ [gmp and google ads connector]: https://github.com/GoogleCloudPlatform/cloud-for-marketing/tree/master/marketing-analytics/activation/gmp-googleads-connector
72
+ [data tasks coordinator]: https://github.com/GoogleCloudPlatform/cloud-for-marketing/tree/master/marketing-analytics/activation/data-tasks-coordinator
73
+ [1]: https://cloud.google.com/functions/docs/writing/background#functions-writing-background-hello-pubsub-node8-10
74
+ [2]: https://cloud.google.com/datastore/docs/concepts/overview#comparison_with_traditional_databases
75
+ [bash]: https://www.gnu.org/software/bash/
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright 2022 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ #######################################
18
+ # Checks whether the BigQuery object (table or view) exists.
19
+ # Globals:
20
+ # GCP_PROJECT
21
+ # DATASET
22
+ # BIGQUERY_LOG_TABLE
23
+ # Arguments:
24
+ # None
25
+ #######################################
26
+ check_existence_in_bigquery() {
27
+ bq show "${1}" >/dev/null 2>&1
28
+ printf '%d' $?
29
+ }
30
+
31
+ #######################################
32
+ # Creates or updates the BigQuery view.
33
+ # Globals:
34
+ # GCP_PROJECT
35
+ # DATASET
36
+ # Arguments:
37
+ # The name of view.
38
+ # The query of view.
39
+ #######################################
40
+ create_or_update_view() {
41
+ local viewName viewQuery
42
+ viewName="${1}"
43
+ viewQuery=${2}
44
+ local action="mk"
45
+ if [[ $(check_existence_in_bigquery "${DATASET}.${viewName}") -eq 0 ]]; then
46
+ action="update"
47
+ fi
48
+ bq "${action}" \
49
+ --use_legacy_sql=false \
50
+ --view "${viewQuery}" \
51
+ --project_id ${GCP_PROJECT} \
52
+ "${DATASET}.${viewName}"
53
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Copyright 2022 Google Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # Google Ads API version
18
+ GOOGLE_ADS_API_VERSION=10
19
+
20
+ #######################################
21
+ # Verify whether the current OAuth token, CID and developer token can work.
22
+ # Globals:
23
+ # None
24
+ # Arguments:
25
+ # MCC CID
26
+ # Developer token
27
+ #######################################
28
+ validate_googleads_account() {
29
+ local cid developerToken accessToken request response
30
+ cid=${1}
31
+ developerToken=${2}
32
+ accessToken=$(get_oauth_access_token)
33
+ request=(
34
+ -H "Accept: application/json"
35
+ -H "Content-Type: application/json"
36
+ -H "developer-token: ${developerToken}"
37
+ -H "Authorization: Bearer ${accessToken}"
38
+ -X POST "https://googleads.googleapis.com/v${GOOGLE_ADS_API_VERSION}/customers/${cid}/googleAds:search"
39
+ -d '{"query": "SELECT customer.id FROM customer"}'
40
+ )
41
+ response=$(curl "${request[@]}" 2>/dev/null)
42
+ local errorCode errorMessage
43
+ errorCode=$(get_value_from_json_string "${response}" "error.code")
44
+ if [[ -n "${errorCode}" ]]; then
45
+ errorMessage=$(get_value_from_json_string "${response}" "error.message")
46
+ printf '%s\n' "Validate failed: ${errorMessage}" >&2
47
+ return 1
48
+ fi
49
+ return 0
50
+ }
51
+
52
+ #######################################
53
+ # Let user input MCC CID and developer token for cronjob(s).
54
+ # Globals:
55
+ # MCC_CIDS
56
+ # DEVELOPER_TOKEN
57
+ # Arguments:
58
+ # None
59
+ #######################################
60
+ set_google_ads_account() {
61
+ printf '%s\n' "Setting up Google Ads account information..."
62
+ local developToken mccCids
63
+ while :; do
64
+ # Developer token
65
+ while [[ -z ${developToken} ]]; do
66
+ printf '%s' " Enter the developer token[${DEVELOPER_TOKEN}]: "
67
+ read -r input
68
+ developToken="${input:-${DEVELOPER_TOKEN}}"
69
+ done
70
+ DEVELOPER_TOKEN="${developToken}"
71
+ mccCids=""
72
+ # MCC CIDs
73
+ while :; do
74
+ printf '%s' " Enter the MCC CID: "
75
+ read -r input
76
+ if [[ -z ${input} ]]; then
77
+ continue
78
+ fi
79
+ input="$(printf '%s' "${input}" | sed -r 's/-//g')"
80
+ printf '%s' " validating ${input}...... "
81
+ validate_googleads_account ${input} ${DEVELOPER_TOKEN}
82
+ if [[ $? -eq 1 ]]; then
83
+ printf '%s\n' "failed.
84
+ Press 'd' to re-enter developer token ["${developToken}"] or
85
+ 'C' to continue with this MCC CID or
86
+ any other key to enter another MCC CID..."
87
+ local any
88
+ read -n1 -s any
89
+ if [[ "${any}" == "d" ]]; then
90
+ developToken=""
91
+ continue 2
92
+ elif [[ "${any}" == "C" ]]; then
93
+ printf '%s\n' "WARNING! Continue with FAILED MCC ${input}."
94
+ else
95
+ continue
96
+ fi
97
+ else
98
+ printf '%s\n' "succeeded."
99
+ fi
100
+ mccCids+=",${input}"
101
+ printf '%s' " Do you want to add another MCC CID? [Y/n]: "
102
+ read -r input
103
+ if [[ ${input} == 'n' || ${input} == 'N' ]]; then
104
+ break
105
+ fi
106
+ done
107
+ # Left Shift one position to remove the first comma.
108
+ # After shifting, MCC_CIDS would like "11111,22222".
109
+ MCC_CIDS="${mccCids:1}"
110
+ printf '%s\n' "Using Google Ads MCC CIDs: ${MCC_CIDS}."
111
+ break
112
+ done
113
+ }
114
+
115
+ printf '%s\n' "Google Ads Bash Library is loaded."
@@ -173,7 +173,7 @@ project ID: [${current_project}]"
173
173
  project=${project:-"${current_project}"}
174
174
  target_project=${project}
175
175
  fi
176
- if [[ -n ${current_project} && \
176
+ if [[ -z ${current_project} || \
177
177
  ${current_project} != "${target_project}" ]];then
178
178
  printf '%s' "Setting the Google Cloud project to [${target_project}]..."
179
179
  gcloud config set project "${target_project}"
@@ -573,7 +573,7 @@ API(s):"
573
573
  printf '%s\n' "OK. OAuth is required by selected API(s)."
574
574
  return 0
575
575
  fi
576
- printf '%s\n' "Selected API(s) require authentication. Please select \
576
+ printf '%s\n' "Selected API(s) require authentication. Choose the \
577
577
  authentication method:"
578
578
  local auths=("Service Account (recommended)" "OAuth")
579
579
  select auth in "${auths[@]}"; do
@@ -604,28 +604,40 @@ check_permissions() {
604
604
  (( STEP += 1 ))
605
605
  printf '%s\n' "Step ${STEP}: Checking current user's access..."
606
606
  local role error
607
- for role in "${!GOOGLE_CLOUD_PERMISSIONS[@]}"; do
608
- printf '%s' " Checking permissions for ${role}... "
609
- local permissions
610
- permissions=(${GOOGLE_CLOUD_PERMISSIONS[${role}]})
611
- local missed
612
- missed=$(get_number_of_missed_permissions "${permissions[@]}")
613
- if [[ $missed -gt 0 ]]; then
614
- message="missed ${missed}, failed"
615
- error=1
607
+ while :; do
608
+ error=0
609
+ for role in "${!GOOGLE_CLOUD_PERMISSIONS[@]}"; do
610
+ printf '%s' " Checking permissions for ${role}... "
611
+ local permissions
612
+ permissions=(${GOOGLE_CLOUD_PERMISSIONS[${role}]})
613
+ local missed
614
+ missed=$(get_number_of_missed_permissions "${permissions[@]}")
615
+ if [[ $missed -gt 0 ]]; then
616
+ message="missed ${missed}, failed"
617
+ error=1
618
+ else
619
+ message='successfully'
620
+ fi
621
+ printf '%s\n' " ${message}."
622
+ done
623
+ if [[ ${error} -gt 0 ]]; then
624
+ printf '%s\n' "Permissions check failed."
625
+ printf '%s\n' "Would you like to login with another account? [Y/n]: "
626
+ local reLogin
627
+ read -r reLogin
628
+ reLogin=${reLogin:-"Y"}
629
+ if [[ ${reLogin} == "Y" || ${reLogin} == "y" ]]; then
630
+ gcloud auth login
631
+ continue
632
+ else
633
+ return 1
634
+ fi
616
635
  else
617
- message='successfully'
636
+ echo "OK. Permissions check passed for Google Cloud project \
637
+ [${GCP_PROJECT}]."
638
+ return 0
618
639
  fi
619
- printf '%s\n' " ${message}."
620
640
  done
621
- if [[ ${error} -gt 0 ]]; then
622
- printf '%s\n' "Permissions check failed."
623
- return 1
624
- else
625
- echo "OK. Permissions check passed for Google Cloud project \
626
- [${GCP_PROJECT}]."
627
- return 0
628
- fi
629
641
  }
630
642
 
631
643
  #######################################
@@ -1129,6 +1141,7 @@ Project. Continuing to enter another bucket..."
1129
1141
  fi
1130
1142
  done
1131
1143
  declare -g "${gcsName}=${bucket}"
1144
+ confirm_bucket_lifecycle "${bucket}"
1132
1145
  }
1133
1146
 
1134
1147
  #######################################
@@ -1149,6 +1162,58 @@ confirm_bucket_with_location() {
1149
1162
  confirm_located_bucket ${gcsName} ${locationName}
1150
1163
  }
1151
1164
 
1165
+ #######################################
1166
+ # Manage the lifecycle of a GCS bucket: setting or removing the GCS lifecycle
1167
+ # rule of 'age'.
1168
+ # See: https://cloud.google.com/storage/docs/lifecycle#age
1169
+ # Arguments:
1170
+ # Bucket name
1171
+ #######################################
1172
+ confirm_bucket_lifecycle() {
1173
+ local bucket bucketMetadata lifecycle
1174
+ bucket="${1}"
1175
+ bucketMetadata="$(get_bucket_metadata "${bucket}")"
1176
+ lifecycle="$(get_value_from_json_string "${bucketMetadata}" "lifecycle")"
1177
+ if [[ -n "${lifecycle}" ]]; then
1178
+ printf '%s\n' "There are lifecycle rules in this bucket: ${lifecycle}."
1179
+ printf '%s' "Would you like to overwrite it? [N/y]:"
1180
+ local confirmContinue
1181
+ read -r confirmContinue
1182
+ confirmContinue=${confirmContinue:-"N"}
1183
+ if [[ ${confirmContinue} == "N" || ${confirmContinue} == "n" ]]; then
1184
+ return 0
1185
+ fi
1186
+ else
1187
+ printf '%s\n' "There is no lifecycle rules in this bucket."
1188
+ printf '%s' "Would you like to create it? [Y/n]:"
1189
+ local confirmContinue
1190
+ read -r confirmContinue
1191
+ confirmContinue=${confirmContinue:-"Y"}
1192
+ if [[ ${confirmContinue} == "N" || ${confirmContinue} == "n" ]]; then
1193
+ return 0
1194
+ fi
1195
+ fi
1196
+ while :; do
1197
+ printf '%s' "Enter the number of days that a file will be kept before it \
1198
+ is automatically removed in the bucket[${bucket}]. (enter 0 to remove all \
1199
+ existing lifecycle rules): "
1200
+ local days
1201
+ read -r days
1202
+ days=${days}
1203
+ if [[ "${days}" =~ ^[0-9]+$ ]]; then
1204
+ local lifecycle
1205
+ if [[ "${days}" == "0" ]]; then
1206
+ lifecycle="{}"
1207
+ else
1208
+ lifecycle='{"rule":[{"action":{"type":"Delete"},"condition":{"age":'\
1209
+ "${days}}}]}"
1210
+ fi
1211
+ gsutil lifecycle set /dev/stdin gs://${bucket} <<< ${lifecycle}
1212
+ return $?
1213
+ fi
1214
+ done
1215
+ }
1216
+
1152
1217
  #######################################
1153
1218
  # Confirm the monitored folder.
1154
1219
  # Globals:
@@ -1507,6 +1572,7 @@ set_authentication_env_for_cloud_functions() {
1507
1572
  create_or_update_cloud_scheduler_for_pubsub(){
1508
1573
  check_authentication
1509
1574
  quit_if_failed $?
1575
+ local location_flag="--location=${REGION}"
1510
1576
  local scheduler_flag=()
1511
1577
  scheduler_flag+=(--schedule="$2")
1512
1578
  scheduler_flag+=(--time-zone="$3")
@@ -1514,13 +1580,13 @@ create_or_update_cloud_scheduler_for_pubsub(){
1514
1580
  scheduler_flag+=(--message-body="$5")
1515
1581
  local exist_job
1516
1582
  exist_job=($(gcloud scheduler jobs list --filter="name~${1}" \
1517
- --format="value(state)"))
1583
+ --format="value(state)" "${location_flag}"))
1518
1584
  local action needPause
1519
1585
  if [[ ${#exist_job[@]} -gt 0 ]]; then
1520
1586
  action="update"
1521
1587
  scheduler_flag+=(--update-attributes=$6)
1522
1588
  if [[ "${exist_job[0]}" == "PAUSED" ]]; then
1523
- gcloud scheduler jobs resume "${1}"
1589
+ gcloud scheduler jobs resume "${1}" "${location_flag}"
1524
1590
  if [[ $? -gt 0 ]]; then
1525
1591
  printf '%s\n' "Failed to resume paused Cloud Scheduler job [${1}]."
1526
1592
  return 1
@@ -1531,9 +1597,9 @@ create_or_update_cloud_scheduler_for_pubsub(){
1531
1597
  action="create"
1532
1598
  scheduler_flag+=(--attributes=$6)
1533
1599
  fi
1534
- gcloud scheduler jobs ${action} pubsub "$1" "${scheduler_flag[@]}"
1600
+ gcloud scheduler jobs ${action} pubsub "$1" "${scheduler_flag[@]}" "${location_flag}"
1535
1601
  if [[ "${needPause}" == "true" ]]; then
1536
- gcloud scheduler jobs pause "${1}"
1602
+ gcloud scheduler jobs pause "${1}" "${location_flag}"
1537
1603
  fi
1538
1604
  }
1539
1605
 
@@ -1921,3 +1987,10 @@ join_string_array() {
1921
1987
  shift
1922
1988
  printf %s "$first" "${@/#/$separator}"
1923
1989
  }
1990
+
1991
+ # Import other bash files.
1992
+ _SELF="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1993
+ source "${_SELF}/google_ads.sh"
1994
+ source "${_SELF}/bigquery.sh"
1995
+
1996
+ printf '%s\n' "Common Bash Library is loaded."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@google-cloud/nodejs-common",
3
- "version": "1.0.4",
3
+ "version": "1.1.1-beta",
4
4
  "description": "A NodeJs common library for solutions based on Cloud Functions",
5
5
  "author": "Google Inc.",
6
6
  "license": "Apache-2.0",
@@ -16,25 +16,26 @@
16
16
  },
17
17
  "homepage": "https://github.com/GoogleCloudPlatform/cloud-for-marketing/blob/master/marketing-analytics/activation/common-libs/nodejs-common/README.md",
18
18
  "dependencies": {
19
- "@google-cloud/aiplatform": "^1.13.0",
20
- "@google-cloud/automl": "^2.5.1",
21
- "@google-cloud/bigquery": "^5.9.2",
19
+ "@google-cloud/aiplatform": "^1.19.0",
20
+ "@google-cloud/automl": "^2.5.2",
21
+ "@google-cloud/bigquery": "^5.12.0",
22
22
  "@google-cloud/datastore": "^6.6.2",
23
- "@google-cloud/firestore": "^4.15.1",
24
- "@google-cloud/logging-winston": "^4.1.1",
25
- "@google-cloud/pubsub": "^2.18.2",
26
- "@google-cloud/storage": "^5.16.0",
23
+ "@google-cloud/firestore": "^5.0.2",
24
+ "@google-cloud/logging-winston": "^4.2.2",
25
+ "@google-cloud/pubsub": "^2.19.0",
26
+ "@google-cloud/storage": "^5.18.3",
27
+ "@google-cloud/scheduler": "^2.3.0",
27
28
  "gaxios": "^4.3.2",
28
- "google-ads-api": "^9.0.0",
29
- "google-ads-node": "^7.0.0",
30
- "google-auth-library": "^7.10.2",
31
- "googleapis": "^91.0.0",
29
+ "google-ads-api": "^10.0.1",
30
+ "google-ads-node":"^8.0.1",
31
+ "google-auth-library": "^7.14.1",
32
+ "googleapis": "^100.0.0",
32
33
  "soap": "^0.43.0",
33
- "winston": "^3.3.3",
34
+ "winston": "^3.7.2",
34
35
  "lodash": "^4.17.21"
35
36
  },
36
37
  "devDependencies": {
37
- "jasmine": "^3.5.0"
38
+ "jasmine": "^4.0.2"
38
39
  },
39
40
  "scripts": {
40
41
  "test": "node node_modules/jasmine/bin/jasmine"
@@ -37,9 +37,11 @@ class AdsDataHub {
37
37
  *
38
38
  * @param {GaxiosOptions|undefined=} options Used to setup for tests.
39
39
  * @param {string|undefined=} customerId ADH customer id.
40
+ * @param {!Object<string,string>=} env The environment object to hold env
41
+ * variables.
40
42
  */
41
- constructor(options, customerId = undefined) {
42
- const authClient = new AuthClient(API_SCOPES);
43
+ constructor(options, customerId = undefined, env = process.env) {
44
+ const authClient = new AuthClient(API_SCOPES, env);
43
45
  this.auth = authClient.getDefaultAuth();
44
46
  /** @const{GaxiosOptions} */ this.options = options || {};
45
47
  /** @const{string|undefined=} */ this.customerId = customerId;
@@ -32,11 +32,11 @@ const API_VERSION = 'v1';
32
32
  * Google cloud client libraries.
33
33
  */
34
34
  class CloudPlatformApis {
35
- constructor(projectId = process.env['GCP_PROJECT']) {
35
+ constructor(env = process.env) {
36
36
  /** @const {!AuthClient} */
37
- const authClient = new AuthClient(API_SCOPES);
38
- this.auth = authClient.getApplicationDefaultCredentials();
39
- this.projectId = projectId;
37
+ const authClient = new AuthClient(API_SCOPES, env);
38
+ this.auth = authClient.getDefaultAuth();
39
+ this.projectId = env['GCP_PROJECT'];
40
40
  }
41
41
 
42
42
  /**
@@ -56,8 +56,13 @@ let RequestBody;
56
56
  * https://developers.google.com/bid-manager/how-tos/authorizing
57
57
  */
58
58
  class DoubleClickBidManager {
59
- constructor() {
60
- const authClient = new AuthClient(API_SCOPES);
59
+ /**
60
+ * @constructor
61
+ * @param {!Object<string,string>=} env The environment object to hold env
62
+ * variables.
63
+ */
64
+ constructor(env = process.env) {
65
+ const authClient = new AuthClient(API_SCOPES, env);
61
66
  const auth = authClient.getDefaultAuth();
62
67
  /** @const {!google.doubleclickbidmanager} */
63
68
  this.instance = google.doubleclickbidmanager({
@@ -104,6 +109,20 @@ class DoubleClickBidManager {
104
109
  return response.data.queryId;
105
110
  }
106
111
 
112
+ /**
113
+ * Deletes a query.
114
+ * @param {number} queryId
115
+ * @return {!Promise<boolean>} Whether the query was deleted.
116
+ */
117
+ async deleteQuery(queryId) {
118
+ try {
119
+ await this.instance.queries.deletequery({ queryId });
120
+ return true;
121
+ } catch (error) {
122
+ console.error(error);
123
+ return false;
124
+ }
125
+ }
107
126
  }
108
127
 
109
128
  module.exports = {
@@ -31,6 +31,8 @@ const {
31
31
  services: {
32
32
  UploadClickConversionsRequest,
33
33
  UploadClickConversionsResponse,
34
+ UploadConversionAdjustmentsRequest,
35
+ UploadConversionAdjustmentsResponse,
34
36
  UploadUserDataRequest,
35
37
  UploadUserDataResponse,
36
38
  UserDataOperation,
@@ -51,8 +53,9 @@ const API_SCOPES = Object.freeze(['https://www.googleapis.com/auth/adwords',]);
51
53
 
52
54
  /**
53
55
  * List of properties that will be taken from the data file as elements of a
54
- * conversion.
56
+ * conversion or a conversion adjustment.
55
57
  * @see https://developers.google.com/google-ads/api/reference/rpc/latest/ClickConversion
58
+ * @see https://developers.google.com/google-ads/api/reference/rpc/latest/ConversionAdjustment
56
59
  * @type {Array<string>}
57
60
  */
58
61
  const PICKED_PROPERTIES = [
@@ -65,6 +68,10 @@ const PICKED_PROPERTIES = [
65
68
  'conversion_value',
66
69
  'currency_code',
67
70
  'order_id',
71
+ 'adjustment_type',
72
+ 'adjustment_date_time',
73
+ 'user_agent',
74
+ 'gclid_date_time_pair',
68
75
  ];
69
76
 
70
77
  /**
@@ -88,9 +95,11 @@ const IDENTIFIERS = [
88
95
  const MAX_IDENTIFIERS_PER_USER = 20;
89
96
 
90
97
  /**
91
- * Configuration for uploading click conversions for Google Ads, includes:
98
+ * Configuration for uploading click conversions or conversion adjustments for
99
+ * Google Ads, includes:
92
100
  * gclid, conversion_action, conversion_date_time, conversion_value,
93
- * currency_code, order_id, external_attribution_data, etc.
101
+ * currency_code, order_id, external_attribution_data,
102
+ * adjustment_type, adjustment_date_time, user_agent, gclid_date_time_pair, etc.
94
103
  * @see PICKED_PROPERTIES
95
104
  *
96
105
  * Other properties that will be used to build the conversions but not picked by
@@ -116,12 +125,15 @@ const MAX_IDENTIFIERS_PER_USER = 20;
116
125
  * conversion_value: number,
117
126
  * currency_code:(string|undefined),
118
127
  * order_id: (string|undefined),
119
- * user_identifier_source:(UserIdentifierSource|undefined),
128
+ * adjustment_type: (string|undefined),
129
+ * adjustment_date_time: (!ConversionAdjustmentType|undefined),
130
+ * user_agent: (string|undefined),
131
+ * user_identifier_source:(!UserIdentifierSource|undefined),
120
132
  * custom_variable_tags:(!Array<string>|undefined),
121
133
  * customVariables:(!Object<string,string>|undefined),
122
134
  * }}
123
135
  */
124
- let ClickConversionConfig;
136
+ let ConversionConfig;
125
137
 
126
138
  /**
127
139
  * Configuration for uploading customer match to Google Ads, includes:
@@ -255,7 +267,7 @@ class GoogleAds {
255
267
  * of click conversions.
256
268
  * @param {string} customerId
257
269
  * @param {string} loginCustomerId Login customer account ID (Mcc Account id).
258
- * @param {!ClickConversionConfig} adsConfig Default click conversion params
270
+ * @param {!ConversionConfig} adsConfig Default click conversion params
259
271
  * @return {!SendSingleBatch} Function which can send a batch of hits to
260
272
  * Google Ads API.
261
273
  */
@@ -268,7 +280,7 @@ class GoogleAds {
268
280
  * @return {!BatchResult}
269
281
  */
270
282
  return async (lines, batchId) => {
271
- /** @type {!Array<ClickConversionConfig>} */
283
+ /** @type {!Array<ConversionConfig>} */
272
284
  const conversions = lines.map(
273
285
  (line) => buildClickConversionFromLine(line, adsConfig, customerId));
274
286
  /** @const {BatchResult} */
@@ -300,6 +312,57 @@ class GoogleAds {
300
312
  }
301
313
  }
302
314
 
315
+ /**
316
+ * Returns the function to send out a request to Google Ads API with a batch
317
+ * of conversion adjustments.
318
+ * @param {string} customerId
319
+ * @param {string} loginCustomerId Login customer account ID (Mcc Account id).
320
+ * @param {!ConversionConfig} adsConfig Default conversion adjustments
321
+ * params.
322
+ * @return {!SendSingleBatch} Function which can send a batch of hits to
323
+ * Google Ads API.
324
+ */
325
+ getUploadConversionAdjustmentFn(customerId, loginCustomerId, adsConfig) {
326
+ /**
327
+ * Sends a batch of hits to Google Ads API.
328
+ * @param {!Array<string>} lines Data for single request. It should be
329
+ * guaranteed that it doesn't exceed quota limitation.
330
+ * @param {string} batchId The tag for log.
331
+ * @return {!BatchResult}
332
+ */
333
+ return async (lines, batchId) => {
334
+ /** @type {!Array<ConversionConfig>} */
335
+ const conversions = lines.map(
336
+ (line) => buildClickConversionFromLine(line, adsConfig, customerId));
337
+ /** @const {BatchResult} */
338
+ const batchResult = {
339
+ result: true,
340
+ numberOfLines: lines.length,
341
+ };
342
+ try {
343
+ const response = await this.uploadConversionAdjustments(conversions,
344
+ customerId, loginCustomerId);
345
+ const {results, partial_failure_error: failed} = response;
346
+ if (this.logger.isDebugEnabled()) {
347
+ const orderId = results.map((conversion) => conversion.order_id);
348
+ this.logger.debug('Uploaded order_id:', orderId);
349
+ }
350
+ if (failed) {
351
+ this.logger.info('partial_failure_error:', failed.message);
352
+ const failures = failed.details.map(
353
+ ({value}) => GoogleAdsFailure.decode(value));
354
+ this.extraFailedLines_(batchResult, failures, lines, 0);
355
+ }
356
+ return batchResult;
357
+ } catch (error) {
358
+ this.logger.error(
359
+ `Error in upload conversion adjustments batch: ${batchId}`, error);
360
+ this.updateBatchResultWithError_(batchResult, error, lines, 0);
361
+ return batchResult;
362
+ }
363
+ }
364
+ }
365
+
303
366
  /**
304
367
  * Updates the BatchResult based on errors.
305
368
  *
@@ -434,7 +497,7 @@ class GoogleAds {
434
497
  * Uploads click conversions to google ads account.
435
498
  * It requires an array of click conversions and customer id.
436
499
  * In DEBUG mode, this function will only validate the conversions.
437
- * @param {Array<ClickConversionConfig>} clickConversions ClickConversions
500
+ * @param {Array<ConversionConfig>} clickConversions ClickConversions
438
501
  * @param {string} customerId
439
502
  * @param {string} loginCustomerId Login customer account ID (Mcc Account id).
440
503
  * @return {!Promise<!UploadClickConversionsResponse>}
@@ -451,6 +514,31 @@ class GoogleAds {
451
514
  return customer.conversionUploads.uploadClickConversions(request);
452
515
  }
453
516
 
517
+ /**
518
+ * Uploads conversion adjustments to google ads account.
519
+ * It requires an array of conversion adjustments and customer id.
520
+ * In DEBUG mode, this function will only validate the conversion adjustments.
521
+ * @param {Array<ConversionAdjustment>} conversionAdjustments Conversion
522
+ * adjustments.
523
+ * @param {string} customerId
524
+ * @param {string} loginCustomerId Login customer account ID (Mcc Account id).
525
+ * @return {!Promise<!UploadConversionAdjustmentsResponse>}
526
+ */
527
+ uploadConversionAdjustments(conversionAdjustments, customerId,
528
+ loginCustomerId) {
529
+ this.logger.debug('Upload conversion adjustments for customerId:',
530
+ customerId);
531
+ const customer = this.getGoogleAdsApiCustomer_(loginCustomerId, customerId);
532
+ const request = new UploadConversionAdjustmentsRequest({
533
+ conversion_adjustments: conversionAdjustments,
534
+ customer_id: customerId,
535
+ validate_only: this.debugMode, // when true makes no changes
536
+ partial_failure: true, // Will still create the non-failed entities
537
+ });
538
+ return customer.conversionAdjustmentUploads.uploadConversionAdjustments(
539
+ request);
540
+ }
541
+
454
542
  /**
455
543
  * Returns the id of Conversion Custom Variable with the given tag.
456
544
  * @param {string} tag Custom Variable tag.
@@ -622,7 +710,7 @@ class GoogleAds {
622
710
  /**
623
711
  * Returns a conversion object based the given config and line data.
624
712
  * @param {string} line A JSON string of a conversion data.
625
- * @param {ClickConversionConfig} config Default click conversion params
713
+ * @param {ConversionConfig} config Default click conversion params
626
714
  * @param {string} customerId
627
715
  * @return {object} A conversion
628
716
  */
@@ -657,7 +745,7 @@ const buildClickConversionFromLine = (line, config, customerId) => {
657
745
  }
658
746
 
659
747
  module.exports = {
660
- ClickConversionConfig,
748
+ ConversionConfig,
661
749
  CustomerMatchRecord,
662
750
  CustomerMatchConfig,
663
751
  GoogleAds,
package/src/apis/index.js CHANGED
@@ -88,7 +88,7 @@ exports.bigquery = require('./bigquery.js');
88
88
  * APIs integration class for Google Ads.
89
89
  * @const {{
90
90
  * GoogleAds:!GoogleAds,
91
- * ClickConversionConfig:!ClickConversionConfig,
91
+ * ConversionConfig:!ConversionConfig,
92
92
  * CustomerMatchConfig: !CustomerMatchConfig,
93
93
  * CustomerMatchRecord: !CustomerMatchRecord,
94
94
  * ReportQueryConfig:!ReportQueryConfig,
@@ -17,15 +17,9 @@
17
17
  */
18
18
 
19
19
  'use strict';
20
- const {request} = require('gaxios');
21
- const {JWT, Compute} = require('google-auth-library');
20
+ const { ClientOptions } = require('google-gax');
22
21
  const automl = require('@google-cloud/automl');
23
22
  const google = automl.protos.google;
24
- const AuthClient = require('../apis/auth_client.js');
25
-
26
- const API_SCOPES = Object.freeze([
27
- 'https://www.googleapis.com/auth/cloud-platform',
28
- ]);
29
23
 
30
24
  /**
31
25
  * For version `v1beta1`, BigQuery can be the source and destination.
@@ -40,46 +34,49 @@ const API_SCOPES = Object.freeze([
40
34
  * @type {string}
41
35
  */
42
36
  const API_VERSION = 'v1beta1';
43
- const PredictionServiceClient = automl[API_VERSION].PredictionServiceClient;
37
+ const { PredictionServiceClient } = automl[API_VERSION];
44
38
 
45
39
  /**
46
- * AutoML Tables API doesn't have fully cloud client library support yet. This
47
- * class acts as the single client class for different API requests of AutoML
48
- * Tables API, including:
49
- * 1. 'batch predict' based on Google Cloud Client Library,
50
- * https://googleapis.dev/nodejs/automl/latest/index.html
51
- * 2. 'get Operations' based on REST API, see:
52
- * https://cloud.google.com/automl/docs/reference/rest/v1/projects.locations.operations/get
53
- * https://cloud.google.com/automl-tables/docs/long-operations#get-operation
40
+ * AutoML Tables API class for:
41
+ * 1. start a batch predict job:
42
+ * @see https://cloud.google.com/nodejs/docs/reference/automl/latest/automl/v1beta1.predictionserviceclient#_google_cloud_automl_v1beta1_PredictionServiceClient_batchPredict_member_3_
43
+ * 2. get the status of an operation:
44
+ * @see https://cloud.google.com/nodejs/docs/reference/automl/latest/automl/v1beta1.predictionserviceclient#_google_cloud_automl_v1beta1_PredictionServiceClient_checkBatchPredictProgress_member_1_
54
45
  */
55
46
  class AutoMl {
56
-
57
47
  /**
58
48
  * Initialize an instance.
59
- * @param {{keyFilename:(string|undefined)}} options
49
+ * @param {ClientOptions=} options
60
50
  */
61
51
  constructor(options = {}) {
62
- this.options = options;
52
+ this.client = new PredictionServiceClient(options);
63
53
  }
64
54
 
65
55
  /**
66
56
  * Batch predicts based on Google Cloud Client Library.
67
- * See https://googleapis.dev/nodejs/automl/latest/index.html
68
57
  * @param {string} projectId
69
58
  * @param {string} computeRegion
70
59
  * @param {string} modelId
71
- * @param {google.cloud.automl.v1.IBatchPredictInputConfig} inputConfig
72
- * @param {google.cloud.automl.v1.IBatchPredictOutputConfig} outputConfig
60
+ * @param {google.cloud.automl.v1beta1.IBatchPredictInputConfig} inputConfig
61
+ * @param {google.cloud.automl.v1beta1.IBatchPredictOutputConfig} outputConfig
73
62
  * @return {Promise<string>} Predict operation name.
74
63
  */
75
- async batchPredict(projectId, computeRegion, modelId, inputConfig,
76
- outputConfig) {
77
- const client = new PredictionServiceClient(this.options);
78
- const modelFullId = client.modelPath(projectId, computeRegion, modelId);
79
- const responses = await client.batchPredict({
64
+ async batchPredict(
65
+ projectId,
66
+ computeRegion,
67
+ modelId,
68
+ inputConfig,
69
+ outputConfig
70
+ ) {
71
+ const modelFullId = this.client.modelPath(
72
+ projectId,
73
+ computeRegion,
74
+ modelId
75
+ );
76
+ const responses = await this.client.batchPredict({
80
77
  name: modelFullId,
81
- inputConfig: inputConfig,
82
- outputConfig: outputConfig,
78
+ inputConfig,
79
+ outputConfig,
83
80
  });
84
81
  const operation = responses[1];
85
82
  console.log(`Operation name: ${operation.name}`);
@@ -87,37 +84,20 @@ class AutoMl {
87
84
  }
88
85
 
89
86
  /**
90
- * Gets Operations based on REST API, see:
91
- * https://cloud.google.com/automl/docs/reference/rest/v1/projects.locations.operations/get
92
- * https://cloud.google.com/automl-tables/docs/long-operations#get-operation
87
+ * Gets status of an operation.
93
88
  * @param {string} operationName
94
- * @return {Promise<google.longrunning.Operation>}
89
+ * @return {Promise<{{
90
+ * done: boolean,
91
+ * error: Error|undefined,
92
+ * metadata: OperationMetadata,
93
+ * name: string,
94
+ * }}>}
95
95
  */
96
96
  async getOperation(operationName) {
97
- const url = `https://automl.googleapis.com/${API_VERSION}/${operationName}`;
98
- const headers = await this.getAuthClient_().getRequestHeaders();
99
- const requestOptions = {
100
- method: 'GET',
101
- headers,
102
- url,
103
- };
104
- const response = await request(requestOptions);
105
- return response.data;
97
+ const response = await this.client.checkBatchPredictProgress(operationName);
98
+ const { done, error, metadata, name } = response;
99
+ return { done, error, metadata, name };
106
100
  }
107
-
108
- /**
109
- * Gets authentication client of AutoML API.
110
- * This API belongs to GCP, however it is not fully supported by Google Cloud
111
- * Client Library. So we need to manage some functions on its REST API,
112
- * in the way like we invoke other external APIs.
113
- * @returns {(!JWT|!Compute)}
114
- * @private
115
- */
116
- getAuthClient_() {
117
- /** @const {!AuthClient} */ const authClient = new AuthClient(API_SCOPES);
118
- return authClient.getApplicationDefaultCredentials();
119
- }
120
-
121
101
  }
122
102
 
123
103
  exports.AutoMl = AutoMl;
@@ -30,11 +30,36 @@ const API_VERSION = 'v1';
30
30
  * to get/pause/resume a job.
31
31
  */
32
32
  class CloudScheduler {
33
- constructor(projectId = process.env['GCP_PROJECT']) {
34
- /** @const {!AuthClient} */
35
- const authClient = new AuthClient(API_SCOPES);
36
- this.auth = authClient.getApplicationDefaultCredentials();
37
- this.projectId = projectId;
33
+ constructor(env = process.env, options = {}) {
34
+ if (!options.authClient) {
35
+ /** @const {!AuthClient} */
36
+ const authClient = new AuthClient(API_SCOPES, env);
37
+ /**
38
+ * By default, `AuthClient` (getDefaultAuth()) will return an auth client
39
+ * based on the settings in ENV while the OAuth is the most preferred.
40
+ * This works for most of the external API clients (in the '../apis'
41
+ * folder), however this won't work in the Cloud Functions, as those OAuth
42
+ * token usually won't have enough permission to invoke Google Cloud API.
43
+ * Using the method `getApplicationDefaultCredentials` to force
44
+ * `AuthClient` return an ADC auth client, which will work in the Cloud.
45
+ *
46
+ * Cloud Scheduler API Client Library is used here as Cloud Client Library
47
+ * is still at beta stage. (For the difference, see
48
+ * https://cloud.google.com/apis/docs/client-libraries-explained)
49
+ * Eventually, when we migrate this to the cloud client library, which
50
+ * automatically takes ADC as the authentication method, the 'AuthClient'
51
+ * is not required here and can be removed.
52
+ */
53
+ this.auth = authClient.getApplicationDefaultCredentials();
54
+ } else {
55
+ /**
56
+ * `authClient` can be consumed by cloud client library as the auth
57
+ * client. By passing this in, we can offer more flexible auth clients in
58
+ * test cases for API client library and cloud client library in future.
59
+ */
60
+ this.auth = options.authClient;
61
+ }
62
+ this.projectId = env['GCP_PROJECT'];
38
63
  this.instance = cloudscheduler({
39
64
  version: API_VERSION,
40
65
  auth: this.auth,
@@ -113,8 +138,8 @@ class CloudScheduler {
113
138
  */
114
139
  async getJobs_(name, targetLocations = undefined) {
115
140
  const regex = new RegExp(`/jobs/${name}$`);
116
- const jobs = (await this.listJobs_(targetLocations)).filter(
117
- (job) => regex.test(job));
141
+ const allJobs = await this.listJobs_(targetLocations);
142
+ const jobs = allJobs.filter((job) => regex.test(job));
118
143
  if (jobs.length === 0) console.error(`Can not find job: ${name}`);
119
144
  return jobs;
120
145
  }
@@ -134,23 +159,10 @@ class CloudScheduler {
134
159
  const projectId = await this.getProjectId_();
135
160
  const requestPrefix = `projects/${projectId}/locations`;
136
161
  const jobs = locations.map(async (location) => {
137
- const request = {parent: `${requestPrefix}/${location}`};
138
- try {
139
- const response = await this.instance.projects.locations.jobs.list(
140
- request);
141
- return response.data.jobs.map((job) => job.name);
142
- } catch (error) {
143
- // Currently, listLocations always returns an array with one location.
144
- // Not sure whether this will be changed or not in future. If one day
145
- // the Cloud Scheduler let users to select a location for a job, then
146
- // it may return multiple locations when listLocation, however the
147
- // target job may exist in one of the locations. In this case, when we
148
- // iterate the job with all possible locations to get the complete job
149
- // path to operate, it will likely generate an error for those wrong
150
- // location(s). So set the try-catch here to handle this situation.
151
- console.error(error.message);
152
- return [];
153
- }
162
+ const request = { parent: `${requestPrefix}/${location}` };
163
+ const response = await this.instance.projects.locations.jobs.list(request);
164
+ if (!response.data.jobs) return [];
165
+ return response.data.jobs.map((job) => job.name);
154
166
  });
155
167
  // Waits for all jobs names and flattens nested job name arrays, however
156
168
  // there is no 'flat' available in current Cloud Functions runtime.
@@ -20,8 +20,7 @@
20
20
 
21
21
  const winston = require('winston');
22
22
  const {inspect} = require('util');
23
- const {LoggingWinston} = require('@google-cloud/logging-winston');
24
- const {CloudPlatformApis} = require('../apis/cloud_platform_apis.js');
23
+ const { LoggingWinston } = require('@google-cloud/logging-winston');
25
24
 
26
25
  /**
27
26
  * The result of a batch of data sent to target API. The batch here means the
@@ -498,37 +497,6 @@ const extractObject = (paths) => {
498
497
  };
499
498
  };
500
499
 
501
- /**
502
- * Checks whether the permissions are granted for current authentication.
503
- * This function will be invoked during the deployment of a specific solution,
504
- * e.g. Tentacles, to make sure the operator has the proper permissions to
505
- * carry on. If the operator doesn't have enough permissions, it will exit with
506
- * status code 1 to let the invoker (the Bash installation script) know that it
507
- * doesn't pass.
508
- * @param {!Array<string>} permissions Array of permissions to check.
509
- * @param {string} projectId The Id of Cloud project.
510
- * @return {!Promise<undefined>}
511
- */
512
- const checkPermissions = (permissions,
513
- projectId = process.env['GCP_PROJECT']) => {
514
- const cloudPlatformApis = new CloudPlatformApis(projectId);
515
- return cloudPlatformApis.testIamPermissions(permissions)
516
- .then((grantedPermissions) => {
517
- console.log(grantedPermissions);
518
- grantedPermissions = grantedPermissions || [];
519
- if (grantedPermissions.length < permissions.length) {
520
- const missedPermissions = permissions.filter(
521
- (permission) => grantedPermissions.indexOf(permission) === -1);
522
- console.error(`[MISSED] ${missedPermissions.join(',')}.`);
523
- process.exit(1);
524
- }
525
- })
526
- .catch((error) => {
527
- console.error(`[ERROR] ${error.message}`);
528
- process.exit(1);
529
- });
530
- };
531
-
532
500
  /**
533
501
  * For more details, see:
534
502
  * https://developers.google.com/google-ads/api/docs/rest/design/json-mappings
@@ -565,7 +533,6 @@ module.exports = {
565
533
  replaceParameters,
566
534
  getFilterFunction,
567
535
  extractObject,
568
- checkPermissions,
569
536
  changeNamingFromSnakeToUpperCamel,
570
537
  changeNamingFromSnakeToLowerCamel,
571
538
  };
@@ -18,6 +18,7 @@
18
18
 
19
19
  'use strict';
20
20
 
21
+ const { ClientOptions } = require('google-gax');
21
22
  const {JobServiceClient} = require('@google-cloud/aiplatform');
22
23
 
23
24
  /**
@@ -29,7 +30,7 @@ class VertexAi {
29
30
 
30
31
  /**
31
32
  * Initialize an instance.
32
- * @param {{keyFilename:(string|undefined)}} options
33
+ * @param {ClientOptions=} options
33
34
  */
34
35
  constructor(options = {}) {
35
36
  this.options = options;
@@ -105,9 +106,9 @@ class VertexAi {
105
106
  * @private
106
107
  */
107
108
  getJobServiceClient_(location) {
108
- const clientOptions = {
109
+ const clientOptions = Object.assign({}, this.options, {
109
110
  apiEndpoint: this.getServiceEndpoint_(location),
110
- };
111
+ });
111
112
  return new JobServiceClient(clientOptions);
112
113
  }
113
114
  }