@deenruv/merchant-plugin 1.0.16 → 1.0.17-dev.14

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,39 +1,30 @@
1
1
  import { Product, RequestContext, TransactionalConnection } from "@deenruv/core";
2
- import { content_v2_1 } from "googleapis";
3
2
  import { MerchantPlatformSettingsEntity } from "../entities/platform-integration-settings.entity.js";
4
- import { BaseData, BaseProductData } from "../types.js";
3
+ import { BaseData, BaseProductData, GoogleProcessedProduct, RemoteProduct } from "../types.js";
4
+ import { GoogleMerchantSettings, GoogleWriteOperation, MerchantOperationResult } from "./google-merchant-api.js";
5
5
  import { MerchantStrategyService } from "./merchant-strategy.service.js";
6
+ type GoogleWriteResult = MerchantOperationResult<GoogleWriteOperation>;
6
7
  type OpResult = {
7
- status: "success";
8
- } | {
9
- status: "error";
10
8
  error?: unknown;
9
+ results: GoogleWriteResult[];
10
+ status: "success" | "error";
11
11
  };
12
12
  export declare class GooglePlatformIntegrationService {
13
13
  private readonly connection;
14
14
  private readonly strategy;
15
- private readonly SCOPES;
16
- private readonly google_content_api_version;
17
15
  private readonly logger;
18
16
  private log;
19
17
  private error;
20
- private googleContext;
21
- private googleContextString;
22
18
  constructor(connection: TransactionalConnection, strategy: MerchantStrategyService);
23
- removeOrphanItems(ctx: RequestContext, items: BaseData[]): Promise<void>;
24
- getAllProducts(ctx: RequestContext): Promise<Array<{
19
+ removeOrphanItems(ctx: RequestContext, items: RemoteProduct[]): Promise<void>;
20
+ getAllProducts(ctx: RequestContext): Promise<RemoteProduct[]>;
21
+ getGoogleProduct(ctx: RequestContext, { communicateID }: {
25
22
  communicateID: string;
26
- name?: string;
27
- }>>;
28
- private getAuthorization;
29
- getGoogleProduct({ communicateID }: {
30
- communicateID: string;
31
- }): Promise<content_v2_1.Schema$Product | null>;
23
+ }): Promise<GoogleProcessedProduct | null>;
32
24
  insertProduct<T extends BaseData>(opts: {
33
25
  ctx: RequestContext;
34
26
  data: BaseProductData<T>;
35
27
  entity: Product;
36
- skipCheck?: boolean;
37
28
  }): Promise<OpResult>;
38
29
  updateProduct(opts: {
39
30
  ctx: RequestContext;
@@ -49,15 +40,15 @@ export declare class GooglePlatformIntegrationService {
49
40
  ctx: RequestContext;
50
41
  products: BaseProductData<BaseData>[];
51
42
  }): Promise<OpResult>;
52
- private sendBatch;
43
+ private sendProducts;
44
+ private sendPreparedProducts;
45
+ private createOperations;
46
+ private persistCommunicationIds;
53
47
  private buildPayload;
54
- private mapInsertProducts;
55
- private mapUpdateProducts;
56
- setGoogleSettings(rawSettings?: MerchantPlatformSettingsEntity): Promise<{
57
- autoUpdate: boolean;
58
- accountId: string;
59
- credentials: any;
60
- brand: string;
61
- } | null>;
48
+ validateGoogleSettings(rawSettings: MerchantPlatformSettingsEntity): GoogleMerchantSettings;
49
+ setGoogleSettings(ctx: RequestContext, rawSettings?: MerchantPlatformSettingsEntity): Promise<GoogleMerchantSettings | null>;
50
+ private getAuthorization;
51
+ private closeClients;
52
+ private isNotFoundError;
62
53
  }
63
54
  export {};
@@ -8,341 +8,233 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
- var __rest = (this && this.__rest) || function (s, e) {
12
- var t = {};
13
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
- t[p] = s[p];
15
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
- t[p[i]] = s[p[i]];
19
- }
20
- return t;
21
- };
22
11
  Object.defineProperty(exports, "__esModule", { value: true });
23
12
  exports.GooglePlatformIntegrationService = void 0;
24
13
  const core_1 = require("@deenruv/core");
25
14
  const common_1 = require("@nestjs/common");
26
- const googleapis_1 = require("googleapis");
15
+ const typeorm_1 = require("typeorm");
27
16
  const platform_integration_settings_entity_js_1 = require("../entities/platform-integration-settings.entity.js");
17
+ const google_merchant_api_js_1 = require("./google-merchant-api.js");
28
18
  const merchant_strategy_service_js_1 = require("./merchant-strategy.service.js");
29
- const typeorm_1 = require("typeorm");
19
+ class GoogleMerchantOperationError extends Error {
20
+ constructor(method, results) {
21
+ const failedIds = results
22
+ .filter((result) => result.status === "error")
23
+ .map((result) => result.item.communicateID)
24
+ .join(", ");
25
+ super(`Google ${method} failed for: ${failedIds || "unknown product"}`);
26
+ this.name = "GoogleMerchantOperationError";
27
+ }
28
+ }
30
29
  let GooglePlatformIntegrationService = class GooglePlatformIntegrationService {
31
30
  constructor(connection, strategy) {
32
31
  this.connection = connection;
33
32
  this.strategy = strategy;
34
- this.SCOPES = ["https://www.googleapis.com/auth/content"];
35
- this.google_content_api_version = "v2.1";
36
33
  this.logger = new core_1.Logger();
37
34
  this.log = (message) => this.logger.log(message, "Merchant Platform Service");
38
35
  this.error = (message, err) => this.logger.error(message, err instanceof Error ? err.stack : String(err), "Merchant Platform Service");
39
- this.googleContext = {
40
- channel: "online",
41
- contentLanguage: "pl",
42
- feedLabel: "PL",
43
- };
44
- this.googleContextString = (id) => Object.values(this.googleContext).join(":") + `:${id}`;
45
36
  }
46
37
  async removeOrphanItems(ctx, items) {
47
- const { accountId, client } = await this.getAuthorization();
48
- const payload = items.map((item) => ({
49
- merchantId: accountId,
50
- productId: this.googleContextString(item.communicateID),
51
- }));
52
- if (payload.length > 0) {
53
- await client.products.custombatch({
54
- requestBody: {
55
- entries: payload.map((p) => (Object.assign(Object.assign({}, p), { method: "delete" }))),
56
- },
57
- });
38
+ if (items.length === 0)
39
+ return;
40
+ const authorization = await this.getAuthorization(ctx);
41
+ try {
42
+ const operations = items.map((item) => (0, google_merchant_api_js_1.createGoogleDeleteOperation)(item.communicateID, authorization.settings));
43
+ const results = await (0, google_merchant_api_js_1.executeGoogleWriteOperations)(authorization.clients.productInputs, operations);
44
+ const summary = (0, google_merchant_api_js_1.summarizeMerchantOperations)(results);
45
+ if (summary.status === "error") {
46
+ throw new GoogleMerchantOperationError("delete", results);
47
+ }
48
+ }
49
+ finally {
50
+ await this.closeClients(authorization.clients);
58
51
  }
59
52
  }
60
53
  async getAllProducts(ctx) {
61
- var _a, _b, _c;
62
- const { accountId, client } = await this.getAuthorization();
63
- const collected = [];
64
- let pageToken;
65
- let page = 0;
54
+ const authorization = await this.getAuthorization(ctx);
66
55
  try {
67
- do {
68
- const { data } = await client.products.list({
69
- merchantId: accountId,
70
- pageToken,
71
- maxResults: 250,
72
- });
73
- const resources = (_a = data.resources) !== null && _a !== void 0 ? _a : [];
74
- for (const p of resources) {
75
- if (p.offerId) {
76
- collected.push({
77
- communicateID: p.offerId,
78
- name: (_b = p.title) !== null && _b !== void 0 ? _b : undefined,
79
- });
80
- }
81
- }
82
- pageToken = (_c = data.nextPageToken) !== null && _c !== void 0 ? _c : undefined;
83
- page++;
84
- if (page > 500) {
85
- this.error("Aborting products pagination: too many pages");
86
- break;
87
- }
88
- } while (pageToken);
89
- return collected;
56
+ return await (0, google_merchant_api_js_1.collectGoogleProductsForDataSource)(authorization.clients.products, authorization.settings.accountId, authorization.settings.dataSource);
90
57
  }
91
- catch (e) {
92
- this.error("Failed to retrieve products from Google", e);
93
- return [];
58
+ catch (error) {
59
+ this.error("Failed to retrieve products from Google", error);
60
+ throw error;
61
+ }
62
+ finally {
63
+ await this.closeClients(authorization.clients);
94
64
  }
95
65
  }
96
- async getAuthorization() {
97
- const settings = await this.setGoogleSettings();
98
- if (!settings)
99
- throw new Error("Google platform settings not found");
100
- const { accountId, credentials } = settings;
101
- const auth = new googleapis_1.google.auth.GoogleAuth({
102
- credentials,
103
- scopes: this.SCOPES,
104
- });
105
- const client = googleapis_1.google.content({
106
- version: this.google_content_api_version,
107
- auth,
108
- });
109
- if (!client)
110
- throw new Error("Content API client not found");
111
- if (!accountId)
112
- throw new Error("Merchant ID not found");
113
- return Object.assign({ client }, settings);
114
- }
115
- async getGoogleProduct({ communicateID }) {
116
- var _a, _b;
117
- const { accountId, client } = await this.getAuthorization();
66
+ async getGoogleProduct(ctx, { communicateID }) {
67
+ const authorization = await this.getAuthorization(ctx);
118
68
  try {
119
- const response = await client.products.get({
120
- merchantId: accountId,
121
- productId: this.googleContextString(communicateID),
69
+ const [product] = await authorization.clients.products.getProduct({
70
+ name: (0, google_merchant_api_js_1.buildGoogleProductName)(authorization.settings.accountId, communicateID),
122
71
  });
123
- return (_a = response.data) !== null && _a !== void 0 ? _a : null;
72
+ return product !== null && product !== void 0 ? product : null;
124
73
  }
125
- catch (e) {
126
- const err = e;
127
- if (((_b = err.response) === null || _b === void 0 ? void 0 : _b.status) === 404)
74
+ catch (error) {
75
+ if (this.isNotFoundError(error))
128
76
  return null;
129
- throw e;
77
+ throw error;
78
+ }
79
+ finally {
80
+ await this.closeClients(authorization.clients);
130
81
  }
131
82
  }
132
83
  async insertProduct(opts) {
133
- return this.sendBatch(Object.assign(Object.assign({}, opts), { method: "insert" }));
84
+ return this.sendProducts(Object.assign(Object.assign({}, opts), { method: "insert" }));
134
85
  }
135
86
  async updateProduct(opts) {
136
- return this.sendBatch(Object.assign(Object.assign({}, opts), { method: "update" }));
87
+ return this.sendProducts(Object.assign(Object.assign({}, opts), { method: "update" }));
137
88
  }
138
89
  async deleteProduct(opts) {
139
- return this.sendBatch(Object.assign(Object.assign({}, opts), { method: "delete" }));
90
+ return this.sendProducts(Object.assign(Object.assign({}, opts), { method: "delete" }));
140
91
  }
141
92
  async batchProductsAction(opts) {
142
- var _a, _b, _c, _d, _e;
143
93
  const { ctx, products } = opts;
144
94
  try {
145
- const { accountId, brand, client } = await this.getAuthorization();
146
- const allPayloads = await Promise.all(products.map((p) => this.buildPayload(ctx, p))).then((arr) => arr.flat());
147
- if (allPayloads.length === 0)
148
- return { status: "success" };
149
- const insertProducts = this.mapInsertProducts(allPayloads, brand);
150
- const entries = insertProducts.map((product, i) => ({
151
- batchId: i + 1,
152
- merchantId: accountId,
153
- method: "insert",
154
- product,
155
- }));
156
- const resp = await client.products.custombatch({
157
- requestBody: { entries },
158
- });
159
- if (resp.status !== 200)
160
- throw new Error("Batch insert failed");
161
- const hasErrors = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.some((e) => e.errors);
162
- if (hasErrors)
163
- throw new Error("Per-item insert errors");
164
- this.log(`Batch inserted ${(_e = (_d = (_c = resp.data) === null || _c === void 0 ? void 0 : _c.entries) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : insertProducts.length} product(s)`);
95
+ const payload = [];
165
96
  for (const product of products) {
166
- for (const item of product) {
167
- await this.connection
168
- .getRepository(ctx, core_1.ProductVariant)
169
- .update({ id: item.variantID }, { customFields: { communicateID: item.communicateID } });
170
- }
97
+ payload.push(...(await this.buildPayload(ctx, product)));
171
98
  }
172
- return { status: "success" };
99
+ return await this.sendPreparedProducts(ctx, "insert", payload);
173
100
  }
174
- catch (e) {
175
- this.error("Batch products action failed", e);
176
- return { status: "error", error: e };
101
+ catch (error) {
102
+ this.error("Google bulk insert failed", error);
103
+ return { error, results: [], status: "error" };
177
104
  }
178
105
  }
179
- async sendBatch(opts) {
180
- var _a, _b, _c, _d, _e, _f;
181
- const { ctx, method, data, skipCheck } = opts;
106
+ async sendProducts(opts) {
107
+ const { ctx, method, data } = opts;
182
108
  try {
183
- const basePayload = await this.buildPayload(ctx, data);
184
- if (basePayload.length === 0)
185
- return { status: "success" };
186
- const { accountId, brand, client } = await this.getAuthorization();
187
- let working = basePayload;
188
- if (method === "insert" && !skipCheck) {
189
- const filtered = [];
190
- for (const item of working) {
191
- if (!item.communicateID)
192
- continue;
193
- try {
194
- const exists = await this.getGoogleProduct({
195
- communicateID: item.communicateID,
196
- });
197
- if (!exists)
198
- filtered.push(item);
199
- }
200
- catch (e) {
201
- this.log(`Lookup failed for ${item.communicateID}, attempting insert. ${e}`);
202
- filtered.push(item);
203
- }
109
+ const payload = await this.buildPayload(ctx, data);
110
+ return await this.sendPreparedProducts(ctx, method, payload);
111
+ }
112
+ catch (error) {
113
+ this.error(`Google ${method} failed`, error);
114
+ return { error, results: [], status: "error" };
115
+ }
116
+ }
117
+ async sendPreparedProducts(ctx, method, payload) {
118
+ if (payload.length === 0) {
119
+ return { results: [], status: "success" };
120
+ }
121
+ const authorization = await this.getAuthorization(ctx);
122
+ let results = [];
123
+ try {
124
+ const operations = this.createOperations(method, payload, authorization.settings);
125
+ results = await (0, google_merchant_api_js_1.executeGoogleWriteOperations)(authorization.clients.productInputs, operations);
126
+ if (method !== "delete") {
127
+ const successfulIds = new Set(results
128
+ .filter((result) => result.status === "success")
129
+ .map((result) => result.item.communicateID));
130
+ const successfulProducts = payload.filter((product) => successfulIds.has(String(product.communicateID)));
131
+ const previousIds = await this.persistCommunicationIds(ctx, successfulProducts, method);
132
+ if (previousIds.length > 0) {
133
+ const cleanupOperations = previousIds.map((communicateID) => (0, google_merchant_api_js_1.createGoogleDeleteOperation)(communicateID, authorization.settings));
134
+ const cleanupResults = await (0, google_merchant_api_js_1.executeGoogleWriteOperations)(authorization.clients.productInputs, cleanupOperations);
135
+ results.push(...cleanupResults);
204
136
  }
205
- working = filtered;
206
- if (working.length === 0)
207
- return { status: "success" };
208
137
  }
209
- let entries = [];
210
- if (method === "insert") {
211
- const products = this.mapInsertProducts(working, brand);
212
- entries = products.map((product, i) => ({
213
- batchId: i + 1,
214
- merchantId: accountId,
215
- method,
216
- product,
217
- }));
138
+ const summary = (0, google_merchant_api_js_1.summarizeMerchantOperations)(results);
139
+ const succeeded = results.length - summary.failures.length;
140
+ this.log(`Google ${method} completed (${succeeded}/${results.length} successful)`);
141
+ if (summary.status === "error") {
142
+ const error = new GoogleMerchantOperationError(method, results);
143
+ this.error(error.message, error);
144
+ return { error, results, status: "error" };
218
145
  }
219
- else if (method === "update") {
220
- const products = this.mapUpdateProducts(working, brand);
221
- if (products.length === 0)
222
- return { status: "success" };
223
- entries = products.map(({ communicateID, product }, i) => ({
224
- batchId: i + 1,
225
- merchantId: accountId,
226
- method,
227
- productId: communicateID,
228
- product,
229
- }));
230
- }
231
- else if (method === "delete") {
232
- entries = working
233
- .filter((p) => !!p.communicateID)
234
- .map((p, i) => ({
235
- batchId: i + 1,
236
- merchantId: accountId,
237
- method,
238
- productId: this.googleContextString(p.communicateID),
239
- }));
240
- }
241
- if (entries.length === 0)
242
- return { status: "success" };
243
- const resp = await client.products.custombatch({
244
- requestBody: { entries },
245
- });
246
- if (resp.status !== 200)
247
- throw new Error(`Batch ${method} HTTP status ${resp.status}`);
248
- const perItemErrors = (_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.entries) === null || _b === void 0 ? void 0 : _b.filter((e) => e.errors);
249
- if (perItemErrors && perItemErrors.length > 0) {
250
- this.error(`Google batch ${method} per-item errors`);
251
- return { status: "error", error: perItemErrors };
252
- }
253
- if (method !== "delete") {
254
- const repo = this.connection.getRepository(ctx, core_1.ProductVariant);
255
- const items = data.filter((d) => d.variantID);
256
- const ids = [...new Set(items.map((i) => i.variantID))];
257
- if (ids.length) {
258
- const variants = await repo.find({ where: { id: (0, typeorm_1.In)(ids) } });
259
- const variantMap = new Map(variants.map((v) => [v.id, v]));
260
- const toDelete = [];
261
- for (const item of items) {
262
- const variant = variantMap.get(item.variantID);
263
- if (!variant)
264
- continue;
265
- const newCommId = item.communicateID;
266
- const prevCommId = (_c = variant.customFields) === null || _c === void 0 ? void 0 : _c.communicateID;
267
- if (method === "update" && prevCommId && prevCommId !== newCommId) {
268
- toDelete.push({
269
- communicateID: prevCommId,
270
- variantID: variant.id,
271
- });
272
- }
273
- variant.customFields = Object.assign(Object.assign({}, variant.customFields), { communicateID: newCommId });
274
- }
275
- if (toDelete.length)
276
- await this.sendBatch({ ctx, method: "delete", data: toDelete });
277
- if (variants.length)
278
- await repo.save(variants, { chunk: 100 });
279
- }
146
+ return { results, status: "success" };
147
+ }
148
+ catch (error) {
149
+ this.error(`Google ${method} failed`, error);
150
+ return { error, results, status: "error" };
151
+ }
152
+ finally {
153
+ await this.closeClients(authorization.clients);
154
+ }
155
+ }
156
+ createOperations(method, payload, settings) {
157
+ if (method === "insert") {
158
+ return payload.map((product) => (0, google_merchant_api_js_1.createGoogleInsertOperation)(product, settings));
159
+ }
160
+ if (method === "update") {
161
+ return payload.map((product) => (0, google_merchant_api_js_1.createGoogleUpdateOperation)(product, settings));
162
+ }
163
+ return payload.map((product) => (0, google_merchant_api_js_1.createGoogleDeleteOperation)(String(product.communicateID), settings));
164
+ }
165
+ async persistCommunicationIds(ctx, products, method) {
166
+ var _a;
167
+ const items = products.filter((product) => product.variantID !== undefined);
168
+ const ids = [...new Set(items.map((item) => String(item.variantID)))];
169
+ if (ids.length === 0)
170
+ return [];
171
+ const repository = this.connection.getRepository(ctx, core_1.ProductVariant);
172
+ const variants = await repository.find({ where: { id: (0, typeorm_1.In)(ids) } });
173
+ const variantMap = new Map(variants.map((variant) => [String(variant.id), variant]));
174
+ const previousIds = new Set();
175
+ for (const item of items) {
176
+ const variant = variantMap.get(String(item.variantID));
177
+ if (!variant)
178
+ continue;
179
+ const nextId = String(item.communicateID);
180
+ const previousId = (_a = variant.customFields) === null || _a === void 0 ? void 0 : _a.communicateID;
181
+ if (method === "update" && previousId && previousId !== nextId) {
182
+ previousIds.add(previousId);
280
183
  }
281
- this.log(`Google batch ${method} done (${(_f = (_e = (_d = resp.data) === null || _d === void 0 ? void 0 : _d.entries) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : entries.length} items)`);
282
- return { status: "success" };
184
+ variant.customFields = Object.assign(Object.assign({}, variant.customFields), { communicateID: nextId });
283
185
  }
284
- catch (e) {
285
- this.error(`Google batch ${method} failed`, e);
286
- return { status: "error", error: e };
186
+ if (variants.length > 0) {
187
+ await repository.save(variants, { chunk: 100 });
287
188
  }
189
+ return [...previousIds];
288
190
  }
289
191
  async buildPayload(ctx, data) {
290
192
  const payload = await this.strategy.prepareGoogleProductPayload(ctx, data);
291
- return (payload !== null && payload !== void 0 ? payload : []).filter((p) => !!p && !!p.communicateID);
292
- }
293
- mapInsertProducts(payload, brand) {
294
- return payload.map((_a) => {
295
- var { communicateID, variantID } = _a, rest = __rest(_a, ["communicateID", "variantID"]);
296
- return (Object.assign(Object.assign(Object.assign({ offerId: communicateID.toString() }, rest), this.googleContext), { brand }));
297
- });
193
+ return (payload !== null && payload !== void 0 ? payload : []).filter((product) => Boolean(product &&
194
+ String(product.communicateID).length > 0 &&
195
+ product.productAttributes));
298
196
  }
299
- mapUpdateProducts(payload, brand) {
300
- return payload
301
- .filter((p) => !!p.communicateID)
302
- .map((_a) => {
303
- var { communicateID, variantID } = _a, rest = __rest(_a, ["communicateID", "variantID"]);
304
- delete rest.offerId;
305
- delete rest.feedLabel;
306
- delete rest.contentLanguage;
307
- delete rest.channel;
308
- const product = Object.assign(Object.assign({}, rest), { brand });
309
- return {
310
- communicateID: this.googleContextString(communicateID),
311
- product,
312
- };
313
- });
197
+ validateGoogleSettings(rawSettings) {
198
+ return (0, google_merchant_api_js_1.parseGoogleMerchantSettings)(rawSettings.entries);
314
199
  }
315
- async setGoogleSettings(rawSettings) {
316
- var _a, _b;
200
+ async setGoogleSettings(ctx, rawSettings) {
317
201
  let settings = rawSettings;
318
202
  if (!settings) {
319
203
  settings = await this.connection
320
- .getRepository(core_1.RequestContext.empty(), platform_integration_settings_entity_js_1.MerchantPlatformSettingsEntity)
204
+ .getRepository(ctx, platform_integration_settings_entity_js_1.MerchantPlatformSettingsEntity)
321
205
  .findOne({ relations: ["entries"], where: { platform: "google" } });
322
206
  }
207
+ return settings ? this.validateGoogleSettings(settings) : null;
208
+ }
209
+ async getAuthorization(ctx) {
210
+ const settings = await this.setGoogleSettings(ctx);
323
211
  if (!settings)
324
- return null;
325
- const getVal = (k) => { var _a; return (_a = settings.entries.find((e) => e.key === k)) === null || _a === void 0 ? void 0 : _a.value; };
326
- const autoUpdate = getVal("autoUpdate");
327
- const accountId = getVal("merchantId");
328
- const brand = (_a = getVal("brand")) !== null && _a !== void 0 ? _a : "";
329
- let credentials = null;
330
- try {
331
- credentials = JSON.parse((_b = getVal("credentials")) !== null && _b !== void 0 ? _b : "null");
332
- }
333
- catch (_c) {
334
- this.log("Error parsing credentials");
335
- return null;
336
- }
337
- if (!accountId || !credentials || !brand)
338
- return null;
212
+ throw new Error("Google platform settings not found");
339
213
  return {
340
- autoUpdate: String(autoUpdate).toLowerCase() === "true",
341
- accountId,
342
- credentials,
343
- brand,
214
+ clients: (0, google_merchant_api_js_1.createGoogleMerchantClients)(settings.credentials),
215
+ settings,
344
216
  };
345
217
  }
218
+ async closeClients(clients) {
219
+ for (const client of [clients.products, clients.productInputs]) {
220
+ try {
221
+ await client.close();
222
+ }
223
+ catch (error) {
224
+ this.error("Failed to close Google Merchant API client", error);
225
+ }
226
+ }
227
+ }
228
+ isNotFoundError(error) {
229
+ var _a;
230
+ if (typeof error !== "object" || error === null)
231
+ return false;
232
+ const candidate = error;
233
+ return (candidate.code === 5 ||
234
+ candidate.code === 404 ||
235
+ candidate.code === "404" ||
236
+ ((_a = candidate.response) === null || _a === void 0 ? void 0 : _a.status) === 404);
237
+ }
346
238
  };
347
239
  exports.GooglePlatformIntegrationService = GooglePlatformIntegrationService;
348
240
  exports.GooglePlatformIntegrationService = GooglePlatformIntegrationService = __decorate([