google-ads-api 14.2.0 → 16.0.0-rest-beta0

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.
@@ -1,12 +1,12 @@
1
1
  import allProtos, { protos } from "google-ads-node";
2
- export declare const VERSION: "v14";
3
- export import common = protos.google.ads.googleads.v14.common;
4
- export import errors = protos.google.ads.googleads.v14.errors;
5
- export import resources = protos.google.ads.googleads.v14.resources;
6
- export import services = protos.google.ads.googleads.v14.services;
7
- export import internalEnums = protos.google.ads.googleads.v14.enums;
2
+ export declare const VERSION: "v16";
3
+ export import common = protos.google.ads.googleads.v16.common;
4
+ export import errors = protos.google.ads.googleads.v16.errors;
5
+ export import resources = protos.google.ads.googleads.v16.resources;
6
+ export import services = protos.google.ads.googleads.v16.services;
7
+ export import internalEnums = protos.google.ads.googleads.v16.enums;
8
8
  export { enums } from "./autogen/enums";
9
- export { fields } from "./autogen/fields";
9
+ export { fields, fieldDataTypes } from "./autogen/fields";
10
10
  export { GoogleAdsServiceClient } from "google-ads-node";
11
11
  export declare type AllServices = Omit<typeof allProtos, typeof VERSION>;
12
12
  export declare type ServiceName = keyof Omit<typeof allProtos, typeof VERSION>;
@@ -1,22 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.longrunning = exports.protobuf = exports.GoogleAdsServiceClient = exports.fields = exports.enums = exports.internalEnums = exports.services = exports.resources = exports.errors = exports.common = exports.VERSION = void 0;
3
+ exports.longrunning = exports.protobuf = exports.GoogleAdsServiceClient = exports.fieldDataTypes = exports.fields = exports.enums = exports.internalEnums = exports.services = exports.resources = exports.errors = exports.common = exports.VERSION = void 0;
4
4
  const google_ads_node_1 = require("google-ads-node");
5
5
  const version_1 = require("../version");
6
6
  // "as vN" is required to avoid type issues later on
7
7
  exports.VERSION = version_1.googleAdsVersion;
8
8
  // -- Expose the googleads generated types --
9
9
  // The namespace path is shortened for ease of use
10
- exports.common = google_ads_node_1.protos.google.ads.googleads.v14.common;
11
- exports.errors = google_ads_node_1.protos.google.ads.googleads.v14.errors;
12
- exports.resources = google_ads_node_1.protos.google.ads.googleads.v14.resources;
13
- exports.services = google_ads_node_1.protos.google.ads.googleads.v14.services;
10
+ exports.common = google_ads_node_1.protos.google.ads.googleads.v16.common;
11
+ exports.errors = google_ads_node_1.protos.google.ads.googleads.v16.errors;
12
+ exports.resources = google_ads_node_1.protos.google.ads.googleads.v16.resources;
13
+ exports.services = google_ads_node_1.protos.google.ads.googleads.v16.services;
14
14
  // We compile enums ourselves, the Google ones should be used internally only
15
- exports.internalEnums = google_ads_node_1.protos.google.ads.googleads.v14.enums;
15
+ exports.internalEnums = google_ads_node_1.protos.google.ads.googleads.v16.enums;
16
16
  var enums_1 = require("./autogen/enums");
17
17
  Object.defineProperty(exports, "enums", { enumerable: true, get: function () { return enums_1.enums; } });
18
18
  var fields_1 = require("./autogen/fields");
19
19
  Object.defineProperty(exports, "fields", { enumerable: true, get: function () { return fields_1.fields; } });
20
+ Object.defineProperty(exports, "fieldDataTypes", { enumerable: true, get: function () { return fields_1.fieldDataTypes; } });
20
21
  // Common service used for report/query methods
21
22
  var google_ads_node_2 = require("google-ads-node");
22
23
  Object.defineProperty(exports, "GoogleAdsServiceClient", { enumerable: true, get: function () { return google_ads_node_2.GoogleAdsServiceClient; } });
@@ -16,6 +16,7 @@ export declare class Service {
16
16
  get credentials(): CustomerCredentials;
17
17
  protected get callHeaders(): CallHeaders;
18
18
  private getCredentials;
19
+ getAccessToken(): Promise<string>;
19
20
  protected loadService<T = AllServices>(service: ServiceName): T;
20
21
  protected getGoogleAdsError(error: Error): errors.GoogleAdsFailure | Error;
21
22
  private decodeGoogleAdsFailureBuffer;
@@ -21,6 +21,11 @@ const serviceCache = new ttlcache_1.default({
21
21
  await service.close();
22
22
  },
23
23
  });
24
+ // A global access token cache used by REST calls. Issued tokens expire after 1 hour.
25
+ const accessTokenCache = new ttlcache_1.default({
26
+ max: 100000,
27
+ ttl: 50 * 60 * 1000, // 50 minutes
28
+ });
24
29
  class Service {
25
30
  constructor(clientOptions, customerOptions, hooks) {
26
31
  this.clientOptions = clientOptions;
@@ -48,12 +53,30 @@ class Service {
48
53
  }
49
54
  return headers;
50
55
  }
56
+ // Used only by gRPC calls
51
57
  getCredentials() {
52
58
  const sslCreds = google_gax_1.grpc.credentials.createSsl();
53
59
  const authClient = new google_auth_library_1.UserRefreshClient(this.clientOptions.client_id, this.clientOptions.client_secret, this.customerOptions.refresh_token);
54
60
  const credentials = google_gax_1.grpc.credentials.combineChannelCredentials(sslCreds, google_gax_1.grpc.credentials.createFromGoogleCredential(authClient));
55
61
  return credentials;
56
62
  }
63
+ // Used only by REST calls
64
+ async getAccessToken() {
65
+ const cachedToken = accessTokenCache.get(this.customerOptions.refresh_token);
66
+ if (cachedToken) {
67
+ return cachedToken;
68
+ }
69
+ const oAuth2Client = new google_auth_library_1.OAuth2Client(this.clientOptions.client_id, this.clientOptions.client_secret);
70
+ oAuth2Client.setCredentials({
71
+ refresh_token: this.customerOptions.refresh_token,
72
+ });
73
+ const { token } = await oAuth2Client.getAccessToken();
74
+ if (typeof token !== "string") {
75
+ throw new Error("Failed to retrieve access token");
76
+ }
77
+ accessTokenCache.set(this.customerOptions.refresh_token, token);
78
+ return token;
79
+ }
57
80
  loadService(service) {
58
81
  const serviceCacheKey = `${service}_${this.customerOptions.refresh_token}`;
59
82
  if (serviceCache.has(serviceCacheKey)) {
@@ -1,4 +1,6 @@
1
+ /// <reference types="node" />
1
2
  /// <reference types="jest" />
3
+ import { Readable } from "stream";
2
4
  import { Customer } from "./customer";
3
5
  import { Hooks } from "./hooks";
4
6
  import { errors, GoogleAdsServiceClient, services } from "./protos";
@@ -12,7 +14,39 @@ export declare const MOCK_LOGIN_CID = "MOCK LOGIN CID";
12
14
  export declare const mockGaqlQuery = "SELECT campaign.resource_name FROM campaign LIMIT 1";
13
15
  export declare const mockReportOptions: ReportOptions;
14
16
  export declare const mockMutations: MutateOperation<any>[];
17
+ export declare const mockSearchRawResult: {
18
+ totalResultsCount: number;
19
+ results: {
20
+ campaign: {
21
+ resourceName: string;
22
+ };
23
+ }[];
24
+ }[];
25
+ export declare const mockSearchRawResultWithSummaryRow: ({
26
+ totalResultsCount: number;
27
+ results: {
28
+ campaign: {
29
+ resourceName: string;
30
+ };
31
+ }[];
32
+ summaryRow?: undefined;
33
+ } | {
34
+ summaryRow: {
35
+ metrics: {
36
+ clicks: number;
37
+ impressions: number;
38
+ };
39
+ };
40
+ totalResultsCount?: undefined;
41
+ results?: undefined;
42
+ })[];
15
43
  export declare const mockQueryReturnValue: services.IGoogleAdsRow[];
44
+ export declare const mockQueryReturnValueWithSummaryRow: services.IGoogleAdsRow[];
45
+ export declare const mockQueryReturnValueUnparsed: {
46
+ campaign: {
47
+ resourceName: string;
48
+ };
49
+ }[];
16
50
  export declare const mockSummaryRow: services.IGoogleAdsRow;
17
51
  export declare const mockTotalResultsCount = 23;
18
52
  export declare const mockMutationReturnValue: services.MutateGoogleAdsResponse;
@@ -27,6 +61,10 @@ export declare const mockError: {
27
61
  export declare const mockErrorMessage = "mock error message";
28
62
  export declare const mockParseValue: services.IGoogleAdsRow;
29
63
  export declare const mockParsedValues: services.IGoogleAdsRow[];
64
+ export declare const mockStream: (data?: any) => Readable;
65
+ export declare function mockGetAccessToken(customer: Customer): jest.SpyInstance;
66
+ export declare const mockStreamWithSummaryRow: () => Readable;
67
+ export declare const mockStreamWithBadData: () => Readable;
30
68
  export declare function mockPaginatedSearch(customer: Customer, includeTotalResultsCount?: boolean): jest.SpyInstance;
31
69
  export declare function mockSearchOnce({ customer, response, nextPageToken, includeTotalResultsCount, }: {
32
70
  customer: Customer;
@@ -62,6 +100,7 @@ export declare function mockBuildMutateRequestAndService({ customer, shouldThrow
62
100
  export declare function mockGetGoogleAdsError(customer: Customer): jest.SpyInstance;
63
101
  export declare function mockQuery(customer: Customer): jest.SpyInstance;
64
102
  export declare function mockParse(mockParsedValues: services.IGoogleAdsRow[]): jest.SpyInstance;
103
+ export declare function mockParseRest(mockParsedValues: services.IGoogleAdsRow[]): jest.SpyInstance;
65
104
  export declare function noopParser(rows: services.IGoogleAdsRow[]): services.IGoogleAdsRow[];
66
105
  export declare function mockMethod(): {
67
106
  method(): void;
@@ -22,12 +22,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.newCustomer = exports.failTestIfExecuted = exports.mockMethod = exports.noopParser = exports.mockParse = exports.mockQuery = exports.mockGetGoogleAdsError = exports.mockBuildMutateRequestAndService = exports.mockBuildSearchRequestAndService = exports.mockBuildSearchStreamRequestAndService = exports.mockSearchOnce = exports.mockPaginatedSearch = exports.mockParsedValues = exports.mockParseValue = exports.mockErrorMessage = exports.mockError = exports.mockMutationReturnValue = exports.mockTotalResultsCount = exports.mockSummaryRow = exports.mockQueryReturnValue = exports.mockMutations = exports.mockReportOptions = exports.mockGaqlQuery = exports.MOCK_LOGIN_CID = exports.MOCK_CID = exports.MOCK_REFRESH_TOKEN = exports.MOCK_DEVELOPER_TOKEN = exports.MOCK_CLIENT_SECRET = exports.MOCK_CLIENT_ID = void 0;
29
+ exports.newCustomer = exports.failTestIfExecuted = exports.mockMethod = exports.noopParser = exports.mockParseRest = exports.mockParse = exports.mockQuery = exports.mockGetGoogleAdsError = exports.mockBuildMutateRequestAndService = exports.mockBuildSearchRequestAndService = exports.mockBuildSearchStreamRequestAndService = exports.mockSearchOnce = exports.mockPaginatedSearch = exports.mockStreamWithBadData = exports.mockStreamWithSummaryRow = exports.mockGetAccessToken = exports.mockStream = exports.mockParsedValues = exports.mockParseValue = exports.mockErrorMessage = exports.mockError = exports.mockMutationReturnValue = exports.mockTotalResultsCount = exports.mockSummaryRow = exports.mockQueryReturnValueUnparsed = exports.mockQueryReturnValueWithSummaryRow = exports.mockQueryReturnValue = exports.mockSearchRawResultWithSummaryRow = exports.mockSearchRawResult = exports.mockMutations = exports.mockReportOptions = exports.mockGaqlQuery = exports.MOCK_LOGIN_CID = exports.MOCK_CID = exports.MOCK_REFRESH_TOKEN = exports.MOCK_DEVELOPER_TOKEN = exports.MOCK_CLIENT_SECRET = exports.MOCK_CLIENT_ID = void 0;
27
30
  const stream_1 = require("stream");
28
31
  const customer_1 = require("./customer");
29
32
  const parser = __importStar(require("./parser"));
33
+ const parserRest = __importStar(require("./parserRest"));
30
34
  const protos_1 = require("./protos");
35
+ const lodash_1 = __importDefault(require("lodash"));
31
36
  exports.MOCK_CLIENT_ID = "MOCK CLIENT ID";
32
37
  exports.MOCK_CLIENT_SECRET = "MOCK CLIENT SECRET";
33
38
  exports.MOCK_DEVELOPER_TOKEN = "MOCK DEVELOPER TOKEN";
@@ -43,11 +48,45 @@ exports.mockReportOptions = {
43
48
  exports.mockMutations = [
44
49
  { resource: "abc", entity: "campaign", operation: "create" },
45
50
  ];
51
+ exports.mockSearchRawResult = [
52
+ {
53
+ totalResultsCount: 23,
54
+ results: [
55
+ { campaign: { resourceName: "customers/1/campaigns/11" } },
56
+ { campaign: { resourceName: "customers/2/campaigns/22" } },
57
+ { campaign: { resourceName: "customers/3/campaigns/33" } },
58
+ ],
59
+ },
60
+ ];
61
+ exports.mockSearchRawResultWithSummaryRow = [
62
+ {
63
+ totalResultsCount: 23,
64
+ results: [
65
+ { campaign: { resourceName: "customers/1/campaigns/11" } },
66
+ { campaign: { resourceName: "customers/2/campaigns/22" } },
67
+ { campaign: { resourceName: "customers/3/campaigns/33" } },
68
+ ],
69
+ },
70
+ {
71
+ summaryRow: { metrics: { clicks: 90, impressions: 153 } },
72
+ },
73
+ ];
46
74
  exports.mockQueryReturnValue = [
47
75
  { campaign: { resource_name: "customers/1/campaigns/11" } },
48
76
  { campaign: { resource_name: "customers/2/campaigns/22" } },
49
77
  { campaign: { resource_name: "customers/3/campaigns/33" } },
50
78
  ];
79
+ exports.mockQueryReturnValueWithSummaryRow = [
80
+ { campaign: { resource_name: "customers/1/campaigns/11" } },
81
+ { campaign: { resource_name: "customers/2/campaigns/22" } },
82
+ { campaign: { resource_name: "customers/3/campaigns/33" } },
83
+ { metrics: { clicks: 90, impressions: 153 } },
84
+ ];
85
+ exports.mockQueryReturnValueUnparsed = [
86
+ { campaign: { resourceName: "customers/1/campaigns/11" } },
87
+ { campaign: { resourceName: "customers/2/campaigns/22" } },
88
+ { campaign: { resourceName: "customers/3/campaigns/33" } },
89
+ ];
51
90
  exports.mockSummaryRow = {
52
91
  metrics: { clicks: 90, impressions: 153 },
53
92
  };
@@ -75,17 +114,43 @@ exports.mockParsedValues = [
75
114
  exports.mockParseValue,
76
115
  exports.mockParseValue,
77
116
  ];
117
+ // Returns a stream that emits the provided values
118
+ const mockStream = function (data = exports.mockSearchRawResult) {
119
+ const chunks = lodash_1.default.chunk(JSON.stringify(data), 10).map((c) => c.join("")); // random splits
120
+ const stream = new stream_1.Readable({ objectMode: true });
121
+ chunks.forEach((value) => stream.push(new Buffer(value)));
122
+ stream.push(null);
123
+ return stream;
124
+ };
125
+ exports.mockStream = mockStream;
126
+ function mockGetAccessToken(customer) {
127
+ return (jest
128
+ .spyOn(customer, "getAccessToken")
129
+ // ts-expect-error
130
+ .mockImplementation(async () => {
131
+ return "mockedAccessTokenHere";
132
+ }));
133
+ }
134
+ exports.mockGetAccessToken = mockGetAccessToken;
135
+ const mockStreamWithSummaryRow = function () {
136
+ return (0, exports.mockStream)(exports.mockSearchRawResultWithSummaryRow);
137
+ };
138
+ exports.mockStreamWithSummaryRow = mockStreamWithSummaryRow;
139
+ const mockStreamWithBadData = function () {
140
+ return (0, exports.mockStream)({ results: 66 });
141
+ };
142
+ exports.mockStreamWithBadData = mockStreamWithBadData;
78
143
  function mockPaginatedSearch(customer, includeTotalResultsCount = false) {
79
144
  return (jest
80
145
  // @ts-expect-error private method
81
146
  .spyOn(customer, "paginatedSearch")
82
147
  // @ts-expect-error
83
- .mockImplementation((gaqlQuery, requestOptions, _parser) => {
148
+ .mockImplementation((gaqlQuery, requestOptions) => {
84
149
  const totalResultsCount = includeTotalResultsCount
85
150
  ? exports.mockTotalResultsCount
86
151
  : undefined;
87
152
  return {
88
- response: _parser(exports.mockQueryReturnValue),
153
+ response: exports.mockQueryReturnValue,
89
154
  totalResultsCount,
90
155
  };
91
156
  }));
@@ -221,6 +286,12 @@ function mockParse(mockParsedValues) {
221
286
  return jest.spyOn(parser, "parse").mockImplementation(() => mockParsedValues);
222
287
  }
223
288
  exports.mockParse = mockParse;
289
+ function mockParseRest(mockParsedValues) {
290
+ return jest
291
+ .spyOn(parserRest, "decamelizeKeys")
292
+ .mockImplementation(() => mockParsedValues);
293
+ }
294
+ exports.mockParseRest = mockParseRest;
224
295
  function noopParser(rows) {
225
296
  return rows;
226
297
  }
@@ -47,8 +47,3 @@ export declare function toCamelCase(str: string): string;
47
47
  export declare function toSnakeCase(str: string): string;
48
48
  export declare function recursiveFieldMaskSearch(data: Record<string, any>): string[];
49
49
  export declare function getFieldMask(data: Record<string, any>): protobuf.FieldMask;
50
- export declare function createNextChunkArrivedPromise(): {
51
- newPromise: Promise<unknown>;
52
- resolve: () => void;
53
- reject: (error: Error) => void;
54
- };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createNextChunkArrivedPromise = exports.getFieldMask = exports.recursiveFieldMaskSearch = exports.toSnakeCase = exports.toCamelCase = exports.capitaliseFirstLetter = exports.normaliseQuery = exports.toMicros = exports.fromMicros = void 0;
3
+ exports.getFieldMask = exports.recursiveFieldMaskSearch = exports.toSnakeCase = exports.toCamelCase = exports.capitaliseFirstLetter = exports.normaliseQuery = exports.toMicros = exports.fromMicros = void 0;
4
4
  const protos_1 = require("./protos");
5
5
  /**
6
6
  * @param micros Money value in micros format
@@ -100,18 +100,3 @@ function getFieldMask(data) {
100
100
  });
101
101
  }
102
102
  exports.getFieldMask = getFieldMask;
103
- function createNextChunkArrivedPromise() {
104
- let resolvePromise = () => {
105
- return;
106
- };
107
- let rejectPromise = (error) => {
108
- throw error;
109
- };
110
- const newPromise = new Promise((resolve, reject) => {
111
- // @ts-ignore
112
- resolvePromise = resolve;
113
- rejectPromise = reject;
114
- });
115
- return { newPromise, resolve: resolvePromise, reject: rejectPromise };
116
- }
117
- exports.createNextChunkArrivedPromise = createNextChunkArrivedPromise;
@@ -1 +1 @@
1
- export declare const googleAdsVersion = "v14";
1
+ export declare const googleAdsVersion = "v16";
@@ -1,4 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.googleAdsVersion = void 0;
4
- exports.googleAdsVersion = "v14";
4
+ /*
5
+ How to upgrade google ads version:
6
+ 1. Update google-ads-node & publish to NPM. Check that package for instructions.
7
+ 2. Update google-ads-node & google-gax in package.json. google-gax should be the same version as google-ads-node.
8
+ 3. Update the version in this file
9
+ 4. Update the versions in src/protos/index.ts
10
+ 5. Run `yarn compile` to update the generated files.
11
+ The `tsc` command might fail -- if so, temporarily add @ts-nocheck
12
+ to the top of problematic files so that the compile script can continue.
13
+ After the compile script has run, those @ts-nocheck lines should no longer be required.
14
+ 6. Prettify the generated files so the the diffs are easier to read.
15
+ 7. Check that the diffs are expected and that the generated files are correct. New Gads versions will often add new services, fields, and enums.
16
+ 8. Test with `yarn test`
17
+ 9. Test by linking to a real project and making some real requests.
18
+ 10. Once confident, bump the major version & publish to NPM.
19
+ */
20
+ exports.googleAdsVersion = "v16";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "google-ads-api",
3
- "version": "14.2.0",
3
+ "version": "16.0.0-rest-beta0",
4
4
  "description": "Google Ads API Client Library for Node.js",
5
5
  "repository": "https://github.com/Opteo/google-ads-api",
6
6
  "main": "build/src/index.js",
@@ -11,26 +11,36 @@
11
11
  "test": "jest",
12
12
  "lint": "eslint . --ext .ts",
13
13
  "build": "tsc",
14
- "compile": "tsc && node build/scripts/index.js",
14
+ "compile": "esbuild --bundle --platform=node ./scripts/index.ts --outfile=./build/scripts/index.js && node ./build/scripts/index.js",
15
15
  "prepare": "rm -rf build && npm run build"
16
16
  },
17
17
  "author": "Opteo",
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
20
  "@isaacs/ttlcache": "^1.2.2",
21
- "google-ads-node": "^12.0.2",
21
+ "axios": "^1.6.7",
22
+ "circ-json": "^1.0.4",
23
+ "google-ads-node": "^13.0.0",
22
24
  "google-auth-library": "^7.1.0",
23
- "google-gax": "^4.0.3",
24
- "long": "^4.0.0"
25
+ "google-gax": "^4.3.1",
26
+ "long": "^4.0.0",
27
+ "map-obj": "^4.0.0",
28
+ "stream-json": "^1.8.0"
25
29
  },
26
30
  "devDependencies": {
27
31
  "@types/jest": "^29.0.1",
32
+ "@types/lodash": "^4.14.202",
28
33
  "@types/pluralize": "^0.0.29",
34
+ "@types/stream-json": "^1.7.7",
29
35
  "@typescript-eslint/eslint-plugin": "^4.8.2",
30
36
  "@typescript-eslint/parser": "^4.8.2",
37
+ "axios-mock-adapter": "^1.22.0",
38
+ "esbuild": "^0.20.1",
31
39
  "eslint": "^7.14.0",
32
40
  "jest": "^29.0.3",
41
+ "lodash": "^4.17.21",
33
42
  "pluralize": "^8.0.0",
43
+ "protobufjs": "^7.2.6",
34
44
  "ts-jest": "^29.0.0",
35
45
  "typescript": "^4.1.2"
36
46
  },