google-ads-api 24.1.0 → 25.1.0-beta.0

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.
Files changed (76) hide show
  1. package/README.md +9 -1
  2. package/build/{src → cjs}/client.d.ts +6 -4
  3. package/build/{src → cjs}/client.js +4 -4
  4. package/build/{src → cjs}/customer.d.ts +5 -5
  5. package/build/{src → cjs}/customer.js +24 -20
  6. package/build/{src → cjs}/hooks.d.ts +2 -2
  7. package/build/cjs/index.d.ts +9 -0
  8. package/build/{src → cjs}/index.js +22 -20
  9. package/build/{src → cjs}/parser.d.ts +2 -2
  10. package/build/{src → cjs}/parser.js +5 -5
  11. package/build/{src → cjs}/parserRest.js +7 -7
  12. package/build/{src → cjs}/protos/autogen/enums.d.ts +1679 -1180
  13. package/build/{src → cjs}/protos/autogen/enums.js +1696 -1177
  14. package/build/cjs/protos/autogen/fields.d.ts +1191 -0
  15. package/build/cjs/protos/autogen/fields.js +205 -0
  16. package/build/cjs/protos/autogen/resourceNames.d.ts +1668 -0
  17. package/build/cjs/protos/autogen/resourceNames.js +1669 -0
  18. package/build/{src → cjs}/protos/autogen/serviceFactory.d.ts +206 -215
  19. package/build/{src → cjs}/protos/autogen/serviceFactory.js +483 -554
  20. package/build/cjs/protos/index.d.ts +14 -0
  21. package/build/{src → cjs}/protos/index.js +12 -12
  22. package/build/{src → cjs}/query.d.ts +2 -2
  23. package/build/{src → cjs}/query.js +5 -5
  24. package/build/{src → cjs}/service.d.ts +5 -5
  25. package/build/{src → cjs}/service.js +64 -22
  26. package/build/{src → cjs}/types.d.ts +1 -1
  27. package/build/{src → cjs}/utils.d.ts +1 -1
  28. package/build/{src → cjs}/utils.js +2 -2
  29. package/build/cjs/version.d.ts +1 -0
  30. package/build/{src → cjs}/version.js +1 -1
  31. package/build/esm/client.d.ts +19 -0
  32. package/build/esm/client.js +40 -0
  33. package/build/esm/customer.d.ts +71 -0
  34. package/build/esm/customer.js +502 -0
  35. package/build/esm/hooks.d.ts +160 -0
  36. package/build/esm/hooks.js +1 -0
  37. package/build/esm/index.d.ts +9 -0
  38. package/build/esm/index.js +10 -0
  39. package/build/esm/package.json +1 -0
  40. package/build/esm/parser.d.ts +21 -0
  41. package/build/esm/parser.js +113 -0
  42. package/build/esm/parserRest.d.ts +1 -0
  43. package/build/esm/parserRest.js +112 -0
  44. package/build/esm/protos/autogen/enums.d.ts +6002 -0
  45. package/build/esm/protos/autogen/enums.js +6401 -0
  46. package/build/esm/protos/autogen/fields.d.ts +1191 -0
  47. package/build/esm/protos/autogen/fields.js +202 -0
  48. package/build/esm/protos/autogen/resourceNames.d.ts +1668 -0
  49. package/build/esm/protos/autogen/resourceNames.js +1475 -0
  50. package/build/esm/protos/autogen/serviceFactory.d.ts +1825 -0
  51. package/build/esm/protos/autogen/serviceFactory.js +18795 -0
  52. package/build/esm/protos/index.d.ts +14 -0
  53. package/build/esm/protos/index.js +19 -0
  54. package/build/esm/query.d.ts +62 -0
  55. package/build/esm/query.js +304 -0
  56. package/build/esm/service.d.ts +47 -0
  57. package/build/esm/service.js +222 -0
  58. package/build/esm/types.d.ts +75 -0
  59. package/build/esm/types.js +14 -0
  60. package/build/esm/utils.d.ts +49 -0
  61. package/build/esm/utils.js +108 -0
  62. package/build/esm/version.d.ts +1 -0
  63. package/build/esm/version.js +1 -0
  64. package/package.json +50 -11
  65. package/build/src/index.d.ts +0 -8
  66. package/build/src/protos/autogen/fields.d.ts +0 -1122
  67. package/build/src/protos/autogen/fields.js +0 -644
  68. package/build/src/protos/autogen/resourceNames.d.ts +0 -1609
  69. package/build/src/protos/autogen/resourceNames.js +0 -1982
  70. package/build/src/protos/index.d.ts +0 -14
  71. package/build/src/testUtils.d.ts +0 -107
  72. package/build/src/testUtils.js +0 -333
  73. package/build/src/version.d.ts +0 -1
  74. /package/build/{src → cjs}/hooks.js +0 -0
  75. /package/build/{src → cjs}/parserRest.d.ts +0 -0
  76. /package/build/{src → cjs}/types.js +0 -0
@@ -0,0 +1,502 @@
1
+ import axios from "axios";
2
+ import Chain from "stream-chain";
3
+ import streamJson from "stream-json";
4
+ import StreamArray from "stream-json/streamers/StreamArray.js";
5
+ import { decamelizeKeys } from "./parserRest.js";
6
+ import { errors } from "./protos/index.js";
7
+ import ServiceFactory from "./protos/autogen/serviceFactory.js";
8
+ import { buildQuery } from "./query.js";
9
+ import { googleAdsVersion } from "./version.js";
10
+ const ROWS_PER_STREAMED_CHUNK = 10_000; // From experience, this is what can be expected from the API.
11
+ export class Customer extends ServiceFactory {
12
+ constructor(clientOptions, customerOptions, hooks) {
13
+ super(clientOptions, customerOptions, hooks ?? {});
14
+ }
15
+ /**
16
+ @description Single query using a raw GAQL string.
17
+ @hooks onQueryStart, onQueryError, onQueryEnd
18
+ */
19
+ async query(gaqlQuery, requestOptions = {}) {
20
+ const { response } = await this.querier(gaqlQuery, requestOptions);
21
+ return response;
22
+ }
23
+ /**
24
+ @description Stream query using a raw GAQL string. If a generic type is provided, it must be the type of a single row.
25
+ If a summary row is requested then this will be the last emitted row of the stream.
26
+ @hooks onStreamStart, onStreamError
27
+ @example
28
+ const stream = queryStream<T>(gaqlQuery)
29
+ for await (const row of stream) { ... }
30
+ */
31
+ async *queryStream(gaqlQuery, requestOptions = {}) {
32
+ const stream = this.streamer(gaqlQuery, requestOptions);
33
+ for await (const row of stream) {
34
+ yield row;
35
+ }
36
+ }
37
+ /**
38
+ @description Single query using ReportOptions.
39
+ If a summary row is requested then this will be the first row of the results.
40
+ @hooks onQueryStart, onQueryError, onQueryEnd
41
+ */
42
+ async report(options) {
43
+ const { gaqlQuery, requestOptions } = buildQuery(options);
44
+ const { response } = await this.querier(gaqlQuery, requestOptions, options);
45
+ return response;
46
+ }
47
+ /**
48
+ @description Get the total row count of a report.
49
+ @hooks none
50
+ */
51
+ async reportCount(options) {
52
+ // must get at least one row
53
+ const { gaqlQuery, requestOptions } = buildQuery({ ...options, limit: 1 });
54
+ // We do not allow this field in reportOptions, however it is still a valid request option
55
+ requestOptions.search_settings = {
56
+ return_total_results_count: true,
57
+ return_summary_row: false,
58
+ };
59
+ const useHooks = false; // to avoid cacheing conflicts
60
+ const { totalResultsCount } = await this.querier(gaqlQuery, requestOptions, options, useHooks);
61
+ return totalResultsCount;
62
+ }
63
+ /**
64
+ @description Stream query using ReportOptions. If a generic type is provided, it must be the type of a single row.
65
+ If a summary row is requested then this will be the last emitted row of the stream.
66
+ @hooks onStreamStart, onStreamError
67
+ @example
68
+ const stream = reportStream<T>(reportOptions)
69
+ for await (const row of stream) { ... }
70
+ */
71
+ async *reportStream(reportOptions) {
72
+ const { gaqlQuery, requestOptions } = buildQuery(reportOptions);
73
+ const stream = this.streamer(gaqlQuery, requestOptions, reportOptions);
74
+ for await (const row of stream) {
75
+ yield row;
76
+ }
77
+ }
78
+ /**
79
+ @description Retreive the raw stream using ReportOptions.
80
+ @hooks onStreamStart
81
+ @example
82
+ const stream = reportStreamRaw(reportOptions)
83
+ stream.on('data', (chunk) => { ... }) // a chunk contains up to 10,000 un-parsed rows
84
+ stream.on('error', (error) => { ... })
85
+ stream.on('end', () => { ... })
86
+ */
87
+ async reportStreamRaw(reportOptions) {
88
+ const { gaqlQuery, requestOptions } = buildQuery(reportOptions);
89
+ const baseHookArguments = {
90
+ credentials: this.credentials,
91
+ query: gaqlQuery,
92
+ reportOptions,
93
+ };
94
+ const queryStart = { cancelled: false };
95
+ if (this.hooks.onStreamStart) {
96
+ await this.hooks.onStreamStart({
97
+ ...baseHookArguments,
98
+ cancel: () => {
99
+ queryStart.cancelled = true;
100
+ },
101
+ editOptions: (options) => {
102
+ Object.entries(options).forEach(([key, val]) => {
103
+ // @ts-ignore
104
+ requestOptions[key] = val;
105
+ });
106
+ },
107
+ });
108
+ if (queryStart.cancelled) {
109
+ return;
110
+ }
111
+ }
112
+ const { service, request } = this.buildSearchStreamRequestAndService(gaqlQuery, requestOptions);
113
+ return service.searchStream(request, {
114
+ otherArgs: { headers: this.callHeaders },
115
+ });
116
+ }
117
+ async search(gaqlQuery, requestOptions) {
118
+ const accessToken = await this.getAccessToken();
119
+ try {
120
+ const rawResponse = await axios(this.prepareGoogleAdsServicePostRequestArgs("search", accessToken, {
121
+ data: {
122
+ query: gaqlQuery,
123
+ ...requestOptions,
124
+ },
125
+ }));
126
+ const searchResponse = rawResponse.data;
127
+ const results = searchResponse.results ?? [];
128
+ const response = results.map((row) => this.decamelizeKeysIfNeeded(row));
129
+ const summaryRow = this.decamelizeKeysIfNeeded(searchResponse.summaryRow);
130
+ const nextPageToken = searchResponse.nextPageToken;
131
+ const totalResultsCount = searchResponse.totalResultsCount
132
+ ? +searchResponse.totalResultsCount
133
+ : undefined;
134
+ return { response, nextPageToken, totalResultsCount, summaryRow };
135
+ }
136
+ catch (e) {
137
+ if (e.response?.data.error.details[0]) {
138
+ throw new errors.GoogleAdsFailure(this.decamelizeKeysIfNeeded(e.response.data.error.details[0]));
139
+ }
140
+ throw e;
141
+ }
142
+ }
143
+ async paginatedSearch(gaqlQuery, requestOptions) {
144
+ /*
145
+ When possible, use the searchStream method to avoid the overhead of pagination.
146
+ */
147
+ if (requestOptions.page_size === undefined &&
148
+ requestOptions.search_settings === undefined // If search_settings is set, we can't use searchStream.
149
+ ) {
150
+ // If no pagination or summary options are set, we can use the non-paginated search method.
151
+ const { response } = await this.useStreamToImitateRegularSearch(gaqlQuery, requestOptions);
152
+ return { response };
153
+ }
154
+ const response = [];
155
+ let nextPageToken = undefined;
156
+ const initialSearch = await this.search(gaqlQuery, requestOptions);
157
+ let totalResultsCount = initialSearch.totalResultsCount;
158
+ // Sometimes (when no results?) the totalResultsCount field is not included in the response.
159
+ // In this case, we set it to 0.
160
+ if (requestOptions.search_settings?.return_total_results_count &&
161
+ initialSearch.totalResultsCount === undefined) {
162
+ totalResultsCount = 0;
163
+ }
164
+ let summaryRow = initialSearch.summaryRow;
165
+ response.push(...initialSearch.response);
166
+ nextPageToken = initialSearch.nextPageToken;
167
+ while (nextPageToken) {
168
+ const nextSearch = await this.search(gaqlQuery, {
169
+ ...requestOptions,
170
+ page_token: nextPageToken,
171
+ });
172
+ response.push(...nextSearch.response);
173
+ nextPageToken = nextSearch.nextPageToken;
174
+ if (nextSearch.summaryRow) {
175
+ summaryRow = nextSearch.summaryRow;
176
+ }
177
+ }
178
+ if (summaryRow) {
179
+ response.unshift(summaryRow);
180
+ }
181
+ return { response, totalResultsCount };
182
+ }
183
+ // Google's searchStream method is faster than search, but it does not support all features.
184
+ // When report() is called, we use searchStream if possible, otherwise we use paginatedSearch.
185
+ // Note that just like `paginatedSearch`, this method accumulates results in memory. Use
186
+ // `reportStream` for a more memory-efficient alternative (at the cost of more CPU usage).
187
+ async useStreamToImitateRegularSearch(gaqlQuery, requestOptions) {
188
+ const accessToken = await this.getAccessToken();
189
+ try {
190
+ const args = this.prepareGoogleAdsServicePostRequestArgs("searchStream", accessToken, {
191
+ responseType: "stream",
192
+ data: {
193
+ query: gaqlQuery,
194
+ ...requestOptions,
195
+ },
196
+ });
197
+ const response = await axios(args);
198
+ const stream = response.data;
199
+ const buffers = [];
200
+ let rowCount = -ROWS_PER_STREAMED_CHUNK;
201
+ for await (const data of stream) {
202
+ if (this.clientOptions.max_reporting_rows &&
203
+ !this.gaqlQueryStringIncludesLimit(gaqlQuery)) {
204
+ // This is a quick-and-dirty way to count rows, but it's good enough for our purposes.
205
+ // We want to avoid using a proper JSON streamer here for performance reasons.
206
+ if (data.toString("utf-8").includes(`results":`)) {
207
+ rowCount += ROWS_PER_STREAMED_CHUNK;
208
+ }
209
+ if (rowCount > this.clientOptions.max_reporting_rows) {
210
+ throw this.generateTooManyRowsError();
211
+ }
212
+ }
213
+ buffers.push(data);
214
+ }
215
+ const asString = Buffer.concat(buffers).toString("utf-8");
216
+ const accumulator = [];
217
+ let foundSummaryRow;
218
+ for (const { results, summaryRow } of JSON.parse(asString)) {
219
+ if (summaryRow) {
220
+ foundSummaryRow = this.decamelizeKeysIfNeeded(summaryRow);
221
+ }
222
+ accumulator.push(...(results ?? []).map((row) => {
223
+ return this.decamelizeKeysIfNeeded(row);
224
+ }));
225
+ if (foundSummaryRow) {
226
+ accumulator.unshift(foundSummaryRow);
227
+ }
228
+ }
229
+ return { response: accumulator };
230
+ }
231
+ catch (e) {
232
+ await this.handleStreamError(e);
233
+ throw e; // The line above should always throw.
234
+ }
235
+ }
236
+ async querier(gaqlQuery, requestOptions = {}, reportOptions, useHooks = true) {
237
+ const baseHookArguments = {
238
+ credentials: this.credentials,
239
+ query: gaqlQuery,
240
+ reportOptions,
241
+ };
242
+ if (this.hooks.onQueryStart && useHooks) {
243
+ const queryCancellation = { cancelled: false };
244
+ await this.hooks.onQueryStart({
245
+ ...baseHookArguments,
246
+ cancel: (res) => {
247
+ queryCancellation.cancelled = true;
248
+ queryCancellation.res = res;
249
+ },
250
+ editOptions: (options) => {
251
+ Object.entries(options).forEach(([key, val]) => {
252
+ // @ts-ignore
253
+ requestOptions[key] = val;
254
+ });
255
+ },
256
+ });
257
+ if (queryCancellation.cancelled) {
258
+ return { response: queryCancellation.res };
259
+ }
260
+ }
261
+ try {
262
+ const { response, totalResultsCount } = await this.paginatedSearch(gaqlQuery, requestOptions);
263
+ if (this.hooks.onQueryEnd && useHooks) {
264
+ const queryResolution = { resolved: false };
265
+ await this.hooks.onQueryEnd({
266
+ ...baseHookArguments,
267
+ response,
268
+ resolve: (res) => {
269
+ queryResolution.resolved = true;
270
+ queryResolution.res = res;
271
+ },
272
+ });
273
+ if (queryResolution.resolved) {
274
+ return { response: queryResolution.res, totalResultsCount };
275
+ }
276
+ }
277
+ return { response: response, totalResultsCount };
278
+ }
279
+ catch (searchError) {
280
+ const googleAdsError = this.getGoogleAdsError(searchError);
281
+ if (this.hooks.onQueryError && useHooks) {
282
+ await this.hooks.onQueryError({
283
+ ...baseHookArguments,
284
+ error: googleAdsError,
285
+ });
286
+ }
287
+ throw googleAdsError;
288
+ }
289
+ }
290
+ async *streamer(gaqlQuery, requestOptions = {}, reportOptions) {
291
+ const baseHookArguments = {
292
+ credentials: this.credentials,
293
+ query: gaqlQuery,
294
+ reportOptions,
295
+ };
296
+ if (this.hooks.onStreamStart) {
297
+ const queryStart = { cancelled: false };
298
+ await this.hooks.onStreamStart({
299
+ ...baseHookArguments,
300
+ cancel: () => {
301
+ queryStart.cancelled = true;
302
+ },
303
+ editOptions: (options) => {
304
+ Object.entries(options).forEach(([key, val]) => {
305
+ // @ts-expect-error
306
+ requestOptions[key] = val;
307
+ });
308
+ },
309
+ });
310
+ if (queryStart.cancelled) {
311
+ return;
312
+ }
313
+ }
314
+ try {
315
+ const accessToken = await this.getAccessToken();
316
+ const args = this.prepareGoogleAdsServicePostRequestArgs("searchStream", accessToken, {
317
+ responseType: "stream",
318
+ data: {
319
+ query: gaqlQuery,
320
+ ...requestOptions,
321
+ },
322
+ });
323
+ const response = await axios(args);
324
+ const stream = response.data;
325
+ // The options below help to make the stream less CPU intensive.
326
+ const parser = new streamJson.Parser({
327
+ streamValues: false,
328
+ streamKeys: false,
329
+ packValues: true,
330
+ packKeys: true,
331
+ });
332
+ const pipeline = Chain.chain([stream, parser, StreamArray.streamArray()]);
333
+ let count = 0;
334
+ try {
335
+ for await (const data of pipeline) {
336
+ const results = data.value.results ??
337
+ (data.value.summaryRow ? [data.value.summaryRow] : undefined) ??
338
+ [];
339
+ count += results.length;
340
+ if (this.clientOptions.max_reporting_rows &&
341
+ count > this.clientOptions.max_reporting_rows &&
342
+ !this.gaqlQueryStringIncludesLimit(gaqlQuery)) {
343
+ throw this.generateTooManyRowsError();
344
+ }
345
+ for (const row of results) {
346
+ const parsed = this.decamelizeKeysIfNeeded(row);
347
+ yield parsed;
348
+ }
349
+ }
350
+ }
351
+ finally {
352
+ pipeline.destroy();
353
+ parser.destroy();
354
+ stream.destroy();
355
+ }
356
+ return;
357
+ }
358
+ catch (e) {
359
+ try {
360
+ await this.handleStreamError(e);
361
+ }
362
+ catch (_e) {
363
+ if (this.hooks.onStreamError) {
364
+ await this.hooks.onStreamError({
365
+ ...baseHookArguments,
366
+ error: _e,
367
+ });
368
+ }
369
+ throw _e;
370
+ }
371
+ }
372
+ }
373
+ async handleStreamError(e) {
374
+ if (!e?.response?.data) {
375
+ throw e;
376
+ }
377
+ // The error is a stream, so some effort is required to parse it.
378
+ const stream = e.response.data;
379
+ const pipeline = Chain.chain([
380
+ stream,
381
+ streamJson.parser(),
382
+ StreamArray.streamArray(),
383
+ ]);
384
+ const defaultErrorMessage = "Unknown GoogleAdsFailure";
385
+ let googleAdsFailure = new Error(defaultErrorMessage);
386
+ // Only throw the first error.
387
+ pipeline.once("data", (data) => {
388
+ if (data?.value?.error?.details?.[0]) {
389
+ googleAdsFailure = new errors.GoogleAdsFailure(this.decamelizeKeysIfNeeded(data.value.error.details[0]));
390
+ }
391
+ else {
392
+ googleAdsFailure = new Error(data?.value?.error?.message ?? defaultErrorMessage, { cause: data?.value?.error ?? data?.value });
393
+ }
394
+ });
395
+ // Must always reject.
396
+ await new Promise((_, reject) => {
397
+ pipeline.on("end", () => reject(googleAdsFailure));
398
+ pipeline.on("error", (err) => reject(err));
399
+ });
400
+ }
401
+ /**
402
+ * @description Creates, updates, or removes resources. This method supports atomic transactions
403
+ * with multiple types of resources. For example, you can atomically create a campaign and a
404
+ * campaign budget, or perform up to thousands of mutates atomically.
405
+ * @hooks onMutationStart, onMutationError, onMutationEnd
406
+ */
407
+ async mutateResources(mutations, mutateOptions = {}) {
408
+ const baseHookArguments = {
409
+ credentials: this.credentials,
410
+ method: "GoogleAdsService.mutate",
411
+ mutations,
412
+ isServiceCall: false,
413
+ };
414
+ if (this.hooks.onMutationStart) {
415
+ const mutationCancellation = { cancelled: false };
416
+ await this.hooks.onMutationStart({
417
+ ...baseHookArguments,
418
+ cancel: (res) => {
419
+ mutationCancellation.cancelled = true;
420
+ mutationCancellation.res = res;
421
+ },
422
+ editOptions: (options) => {
423
+ Object.entries(options).forEach(([key, val]) => {
424
+ // @ts-ignore
425
+ mutateOptions[key] = val;
426
+ });
427
+ },
428
+ });
429
+ if (mutationCancellation.cancelled) {
430
+ return mutationCancellation.res;
431
+ }
432
+ }
433
+ const { service, request } = this.buildMutationRequestAndService(mutations, mutateOptions);
434
+ try {
435
+ const response = (await service.mutate(request, {
436
+ otherArgs: { headers: this.callHeaders },
437
+ }))[0];
438
+ const parsedResponse = request.partial_failure
439
+ ? this.decodePartialFailureError(response)
440
+ : response;
441
+ if (this.hooks.onMutationEnd) {
442
+ const mutationResolution = { resolved: false };
443
+ await this.hooks.onMutationEnd({
444
+ ...baseHookArguments,
445
+ response: parsedResponse,
446
+ resolve: (res) => {
447
+ mutationResolution.resolved = true;
448
+ mutationResolution.res = res;
449
+ },
450
+ });
451
+ if (mutationResolution.resolved) {
452
+ return mutationResolution.res;
453
+ }
454
+ }
455
+ return parsedResponse;
456
+ }
457
+ catch (mutateError) {
458
+ const googleAdsError = this.getGoogleAdsError(mutateError);
459
+ if (this.hooks.onMutationError) {
460
+ await this.hooks.onMutationError({
461
+ ...baseHookArguments,
462
+ error: googleAdsError,
463
+ });
464
+ }
465
+ throw googleAdsError;
466
+ }
467
+ }
468
+ get googleAdsFields() {
469
+ return {
470
+ searchGoogleAdsFields: async (request) => {
471
+ const service = await this.loadService("GoogleAdsFieldServiceClient");
472
+ return service.searchGoogleAdsFields(request, {
473
+ // @ts-expect-error This method does support call headers
474
+ otherArgs: { headers: this.callHeaders },
475
+ });
476
+ },
477
+ };
478
+ }
479
+ prepareGoogleAdsServicePostRequestArgs(functionName, accessToken, extra) {
480
+ return {
481
+ method: "POST",
482
+ url: `https://googleads.googleapis.com/${googleAdsVersion}/customers/${this.customerOptions.customer_id}/googleAds:${functionName}`,
483
+ headers: {
484
+ Authorization: `Bearer ${accessToken}`,
485
+ ...this.callHeaders,
486
+ },
487
+ ...extra,
488
+ };
489
+ }
490
+ decamelizeKeysIfNeeded(input) {
491
+ if (this.clientOptions.disable_parsing) {
492
+ return input;
493
+ }
494
+ return decamelizeKeys(input);
495
+ }
496
+ gaqlQueryStringIncludesLimit(gaqlQuery) {
497
+ return gaqlQuery.toLowerCase().includes("limit ");
498
+ }
499
+ generateTooManyRowsError() {
500
+ return new Error(`Exceeded the maximum number of rows set by "max_reporting_rows" (${this.clientOptions.max_reporting_rows}).`);
501
+ }
502
+ }
@@ -0,0 +1,160 @@
1
+ import { errors, services } from "./protos/index.js";
2
+ import { CustomerCredentials, MutateOperation, ReportOptions, RequestOptions, MutateOptions } from "./types.js";
3
+ export type BaseRequestHookArgs = {
4
+ credentials: CustomerCredentials;
5
+ query: string;
6
+ reportOptions?: ReportOptions;
7
+ };
8
+ export type BaseMutationHookArgs = {
9
+ credentials: CustomerCredentials;
10
+ method: `${keyof typeof services}.${string}`;
11
+ } & (// Mutation was executed with customer.mutateResources
12
+ {
13
+ mutations: MutateOperation<any>[];
14
+ isServiceCall: false;
15
+ } | {
16
+ mutation: any;
17
+ isServiceCall: true;
18
+ });
19
+ export type BaseServiceHookArgs = {
20
+ credentials: CustomerCredentials;
21
+ method: `${keyof typeof services}.${string}`;
22
+ requestOptions: any;
23
+ };
24
+ type StartHookArgs<T = RequestOptions | MutateOptions | any, A = void> = {
25
+ cancel: A extends void ? () => void : (args?: A) => void;
26
+ editOptions: (options: Partial<T>) => void;
27
+ };
28
+ type ErrorHookArgs = {
29
+ error: errors.GoogleAdsFailure | Error;
30
+ };
31
+ type EndHookArgs<T = services.IGoogleAdsRow[] | services.MutateGoogleAdsResponse> = {
32
+ response?: T;
33
+ resolve: (args: any) => void;
34
+ };
35
+ type HookArgs = StartHookArgs | ErrorHookArgs | EndHookArgs;
36
+ type RequestHook<H extends HookArgs> = (a: BaseRequestHookArgs & H) => void;
37
+ type MutationHook<H extends HookArgs> = (a: BaseMutationHookArgs & H) => void;
38
+ type ServiceHook<H extends HookArgs> = (a: BaseServiceHookArgs & H) => void;
39
+ export type OnQueryStart = RequestHook<StartHookArgs<RequestOptions, any>>;
40
+ export type OnQueryError = RequestHook<ErrorHookArgs>;
41
+ export type OnQueryEnd = RequestHook<EndHookArgs<services.IGoogleAdsRow[]>>;
42
+ export type OnStreamStart = RequestHook<StartHookArgs<RequestOptions, void>>;
43
+ export type OnStreamError = RequestHook<ErrorHookArgs>;
44
+ export type OnMutationStart = MutationHook<StartHookArgs<MutateOptions, any>>;
45
+ export type OnMutationError = MutationHook<ErrorHookArgs>;
46
+ export type OnMutationEnd = MutationHook<EndHookArgs<services.MutateGoogleAdsResponse>>;
47
+ export type OnServiceStart = ServiceHook<StartHookArgs<any, any>>;
48
+ export type OnServiceError = ServiceHook<ErrorHookArgs>;
49
+ export type OnServiceEnd = ServiceHook<EndHookArgs<any>>;
50
+ export interface Hooks {
51
+ /**
52
+ * @description Hook called before execution of a query in the `query` and `report` methods
53
+ * @params `{ credentials, query, reportOptions, cancel, editOptions }`
54
+ * @param credentials customer id, login customer id, linked customer id
55
+ * @param query gaql
56
+ * @param reportOptions
57
+ * @param cancel utility function for cancelling the query. if an argument is provided then the query will return this argument
58
+ * @param editOptions utility function for editing the request options. any request option keys that are passed will be changed
59
+ */
60
+ onQueryStart?: OnQueryStart;
61
+ /**
62
+ * @description Hook called upon a query throwing an error in the `query` and `report` methods
63
+ * @params `{ credentials, query, reportOptions, error }`
64
+ * @param credentials customer id, login customer id, linked customer id
65
+ * @param query gaql
66
+ * @param reportOptions
67
+ * @param error google ads error
68
+ */
69
+ onQueryError?: OnQueryError;
70
+ /**
71
+ * @description Hook called after successful execution of a query in the `query` and `report` methods
72
+ * @params `{ credentials, query, reportOptions, response, resolve }`
73
+ * @param credentials customer id, login customer id, linked customer id
74
+ * @param query gaql
75
+ * @param reportOptions
76
+ * @param response results of the query, not available on reportStream
77
+ * @param resolve utility function for returning an alternative value from the query
78
+ */
79
+ onQueryEnd?: OnQueryEnd;
80
+ /**
81
+ * @description Hook called before execution of a stream in the `reportStream` and `reportStreamRaw` methods
82
+ * @params `{ credentials, query, reportOptions, cancel, editOptions }`
83
+ * @param credentials customer id, login customer id, linked customer id
84
+ * @param query gaql
85
+ * @param reportOptions
86
+ * @param cancel utility function for cancelling the stream
87
+ * @param editOptions utility function for editing the request options. any request option keys that are passed will be changed
88
+ */
89
+ onStreamStart?: OnStreamStart;
90
+ /**
91
+ * @description Hook called upon a stream throwing an error in the `reportStream` method. Will not be called for an error in `reportStreamRaw`
92
+ * @params `{ credentials, query, reportOptions, error }`
93
+ * @param credentials customer id, login customer id, linked customer id
94
+ * @param query gaql
95
+ * @param reportOptions
96
+ * @param error google ads error
97
+ */
98
+ onStreamError?: OnStreamError;
99
+ /**
100
+ * @description Hook called before execution of a mutation
101
+ * @params `{ credentials, mutations, cancel, editOptions }`
102
+ * @param credentials customer id, login customer id, linked customer id
103
+ * @param mutations
104
+ * @param cancel utility function for cancelling the mutation. if an argument is provided then the query/report will return this argument
105
+ * @param editOptions utility function for editing the mutate options. any mutate option keys that are passed will be changed
106
+ */
107
+ onMutationStart?: OnMutationStart;
108
+ /**
109
+ * @description Hook called upon a mutation throwing an error
110
+ * @params `{ credentials, mutations, error }`
111
+ * @param credentials customer id, login customer id, linked customer id
112
+ * @param mutations
113
+ * @param error google ads error
114
+ */
115
+ onMutationError?: OnMutationError;
116
+ /**
117
+ * @description Hook called after successful execution of a mutation
118
+ * @params `{ credentials, mutations, response, resolve }`
119
+ * @param credentials customer id, login customer id, linked customer id
120
+ * @param mutations
121
+ * @param response results of the mutation
122
+ * @param resolve utility function for returning an alternative value from the mutation
123
+ */
124
+ onMutationEnd?: OnMutationEnd;
125
+ /**
126
+ * @description Hook called before execution of a service
127
+ * @params `{ credentials, method, requestOptions }`
128
+ * @param credentials customer id, login customer id, linked customer id
129
+ * @param method
130
+ * @param cancel utility function for cancelling the service. if an argument is provided then the service will return this argument
131
+ * @param editOptions utility function for editing the service options. any service option keys that are passed will be changed
132
+ */
133
+ onServiceStart?: OnServiceStart;
134
+ /**
135
+ * @description Hook called upon a service throwing an error
136
+ * @params `{ credentials, method, error }`
137
+ * @param credentials customer id, login customer id, linked customer id
138
+ * @param method
139
+ * @param error google ads error
140
+ */
141
+ onServiceError?: OnServiceError;
142
+ /**
143
+ * @description Hook called after successful execution of a service
144
+ * @params `{ credentials, method, response, resolve }`
145
+ * @param credentials customer id, login customer id, linked customer id
146
+ * @param method
147
+ * @param response results of the service
148
+ * @param resolve utility function for returning an alternative value from the service
149
+ */
150
+ onServiceEnd?: OnServiceEnd;
151
+ }
152
+ export type HookedCancellation = {
153
+ cancelled: boolean;
154
+ res?: any;
155
+ };
156
+ export type HookedResolution = {
157
+ resolved: boolean;
158
+ res?: any;
159
+ };
160
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export { Client as GoogleAdsApi, ClientOptions } from "./client.js";
2
+ export { common, enums, fields, errors, resources, services, longrunning, protobuf, } from "./protos/index.js";
3
+ export { fromMicros, toMicros } from "./utils.js";
4
+ export { googleAdsVersion } from "./version.js";
5
+ export { parse } from "./parser.js";
6
+ export * as ResourceNames from "./protos/autogen/resourceNames.js";
7
+ export { CustomerOptions, ReportOptions, MutateOperation, Constraint, Constraints, } from "./types.js";
8
+ export { Hooks, OnQueryStart, OnQueryError, OnQueryEnd, OnStreamStart, OnStreamError, OnMutationStart, OnMutationError, OnMutationEnd, OnServiceStart, OnServiceError, OnServiceEnd, } from "./hooks.js";
9
+ export { Customer } from "./customer.js";
@@ -0,0 +1,10 @@
1
+ // Core library client
2
+ export { Client as GoogleAdsApi } from "./client.js";
3
+ // Compiled proto types
4
+ export { common, enums, fields, errors, resources, services, longrunning, protobuf, } from "./protos/index.js";
5
+ // Util functions
6
+ export { fromMicros, toMicros } from "./utils.js";
7
+ export { googleAdsVersion } from "./version.js";
8
+ export { parse } from "./parser.js";
9
+ export * as ResourceNames from "./protos/autogen/resourceNames.js";
10
+ export { Customer } from "./customer.js";
@@ -0,0 +1 @@
1
+ {"type":"module"}