@deenruv/merchant-plugin 1.0.17-dev.18 → 1.0.17-dev.23

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 (34) hide show
  1. package/README.md +14 -0
  2. package/dist/plugin-server/api/platform-integration-admin-resolver.d.ts +20 -1
  3. package/dist/plugin-server/api/platform-integration-admin-resolver.js +44 -19
  4. package/dist/plugin-server/entities/merchant-sync-item.entity.d.ts +14 -0
  5. package/dist/plugin-server/entities/merchant-sync-item.entity.js +56 -0
  6. package/dist/plugin-server/entities/merchant-sync-run.entity.d.ts +19 -0
  7. package/dist/plugin-server/entities/merchant-sync-run.entity.js +72 -0
  8. package/dist/plugin-server/extensions/api-extensions.js +53 -2
  9. package/dist/plugin-server/index.js +10 -1
  10. package/dist/plugin-server/services/google-merchant-api.d.ts +48 -6
  11. package/dist/plugin-server/services/google-merchant-api.js +247 -32
  12. package/dist/plugin-server/services/google-platform-integration.service.d.ts +8 -7
  13. package/dist/plugin-server/services/google-platform-integration.service.js +79 -6
  14. package/dist/plugin-server/services/merchant-sync-history.service.d.ts +25 -0
  15. package/dist/plugin-server/services/merchant-sync-history.service.js +97 -0
  16. package/dist/plugin-server/services/platform-integration.service.d.ts +6 -2
  17. package/dist/plugin-server/services/platform-integration.service.js +53 -29
  18. package/dist/plugin-server/services/subscriber.service.d.ts +32 -4
  19. package/dist/plugin-server/services/subscriber.service.js +141 -23
  20. package/dist/plugin-server/ui/graphql/mutations.ts +7 -0
  21. package/dist/plugin-server/ui/graphql/queries.ts +99 -0
  22. package/dist/plugin-server/ui/pages/GooglePage.tsx +158 -16
  23. package/dist/plugin-server/ui/zeus/const.ts +106 -1
  24. package/dist/plugin-server/ui/zeus/index.ts +482 -10
  25. package/dist/plugin-server/zeus/const.js +104 -1
  26. package/dist/plugin-server/zeus/index.d.ts +492 -6
  27. package/dist/plugin-ui/graphql/mutations.d.ts +9 -4
  28. package/dist/plugin-ui/graphql/mutations.js +6 -0
  29. package/dist/plugin-ui/graphql/queries.d.ts +55 -4
  30. package/dist/plugin-ui/graphql/queries.js +49 -0
  31. package/dist/plugin-ui/pages/GooglePage.js +51 -13
  32. package/dist/plugin-ui/zeus/const.js +104 -1
  33. package/dist/plugin-ui/zeus/index.d.ts +492 -6
  34. package/package.json +8 -7
package/README.md CHANGED
@@ -41,11 +41,22 @@ Google settings page requires:
41
41
  - `credentials` — Google OAuth credential JSON for a service account or an
42
42
  authorized user. Store and distribute this value as a secret.
43
43
  - `brand` — the brand applied to exported product attributes.
44
+ - `contentLanguage` — two-letter product language code (defaults to `pl`).
45
+ - `feedLabel` — Merchant Center feed label (defaults to `PL`).
46
+
47
+ `publicBaseUrl` is supplied by the export strategy. It must produce absolute,
48
+ publicly reachable `http` or `https` product and image URLs. The example server
49
+ reads it from `PUBLIC_URL`, then `HOST_URL`, and only falls back to localhost in
50
+ local development.
44
51
 
45
52
  Product inputs are written only to the configured data source. Merchant API
46
53
  processing is asynchronous, so a processed product might not be readable for
47
54
  several minutes after a successful write.
48
55
 
56
+ After upgrading an existing installation, generate and run a database migration
57
+ for the new `merchant_sync_run` and `merchant_sync_item` history tables before
58
+ starting workers.
59
+
49
60
  #### Deployment prerequisites (documentation only)
50
61
 
51
62
  An operator must complete the following outside this plugin and outside the
@@ -67,6 +78,9 @@ data sources, change Merchant Center configuration, or provision credentials:
67
78
  - Google Merchant Center integration via Merchant API Products v1
68
79
  - Facebook Commerce integration via Facebook Business SDK
69
80
  - Per-platform settings storage and management
81
+ - Live account and data-source connection diagnostics
82
+ - Persistent synchronization run and per-product error history
83
+ - Retried, queued, idempotent Google product updates
70
84
  - Bulk product sync to merchant platforms
71
85
  - Orphan item cleanup for removed products
72
86
  - `communicateID` custom field on ProductVariant for platform communication tracking
@@ -14,13 +14,32 @@ export declare class PlatformIntegrationAdminResolver {
14
14
  getMerchantPlatformInfo(ctx: RequestContext, args: {
15
15
  platform: string;
16
16
  }): Promise<{
17
+ isValidConnection: boolean;
18
+ checkedAt: string;
19
+ connectionStatus: import("../services/google-merchant-api.js").GoogleMerchantConnectionStatus;
20
+ dataSourceVerified: boolean;
21
+ disapprovedProductsCount: number;
22
+ issues: import("../services/google-merchant-api.js").GoogleMerchantProductIssue[];
23
+ issuesCount: number;
24
+ lastError?: Omit<import("../services/google-merchant-api.js").NormalizedGoogleMerchantError, "status"> | undefined;
25
+ latencyMs: number;
26
+ productsCount: number;
27
+ }[] | {
17
28
  productsCount: number;
18
29
  isValidConnection: boolean;
19
30
  }[]>;
31
+ sendAllProductsToMerchantPlatform(ctx: RequestContext, args: {
32
+ platform: string;
33
+ }): Promise<boolean>;
34
+ getMerchantSyncHistory(ctx: RequestContext, args: {
35
+ platform: string;
36
+ take?: number;
37
+ }): Promise<import("../entities/merchant-sync-run.entity.js").MerchantSyncRun[]>;
20
38
  saveMerchantPlatformSettings(ctx: RequestContext, args: {
21
39
  input: MerchantPlatformSettingsEntity;
22
- }): Promise<MerchantPlatformSettingsEntity | undefined>;
40
+ }): Promise<MerchantPlatformSettingsEntity>;
23
41
  removeOrphanItems(ctx: RequestContext, args: {
24
42
  platform: string;
25
43
  }): Promise<boolean>;
44
+ private redactCredentials;
26
45
  }
@@ -26,28 +26,17 @@ let PlatformIntegrationAdminResolver = class PlatformIntegrationAdminResolver {
26
26
  this.facebookPlatformIntegrationService = facebookPlatformIntegrationService;
27
27
  this.platformIntegrationService = platformIntegrationService;
28
28
  }
29
- getMerchantPlatformSettings(ctx, args) {
30
- return this.platformIntegrationService.getBaseSettings(ctx, args.platform);
29
+ async getMerchantPlatformSettings(ctx, args) {
30
+ const settings = await this.platformIntegrationService.getBaseSettings(ctx, args.platform);
31
+ return settings ? this.redactCredentials(settings) : null;
31
32
  }
32
33
  async getMerchantPlatformInfo(ctx, args) {
33
34
  var _a;
34
35
  const settings = await this.platformIntegrationService.getBaseSettings(ctx, args.platform);
35
36
  if (args.platform === "google") {
36
- let isValidConnection = false;
37
- if (settings) {
38
- try {
39
- this.googlePlatformIntegrationService.validateGoogleSettings(settings);
40
- isValidConnection = true;
41
- }
42
- catch (_b) {
43
- isValidConnection = false;
44
- }
45
- }
37
+ const diagnostic = await this.googlePlatformIntegrationService.getConnectionDiagnostic(ctx);
46
38
  return [
47
- {
48
- productsCount: 0,
49
- isValidConnection,
50
- },
39
+ Object.assign(Object.assign({}, diagnostic), { isValidConnection: diagnostic.connectionStatus === "CONNECTED" }),
51
40
  ];
52
41
  }
53
42
  if (args.platform === "facebook") {
@@ -60,20 +49,40 @@ let PlatformIntegrationAdminResolver = class PlatformIntegrationAdminResolver {
60
49
  }
61
50
  return [{ productsCount: 0, isValidConnection: false }];
62
51
  }
52
+ async sendAllProductsToMerchantPlatform(ctx, args) {
53
+ return this.platformIntegrationService.enqueueFullSync(ctx, args.platform);
54
+ }
55
+ async getMerchantSyncHistory(ctx, args) {
56
+ return this.platformIntegrationService.getSyncHistory(ctx, args.platform, args.take);
57
+ }
63
58
  async saveMerchantPlatformSettings(ctx, args) {
59
+ var _a, _b;
60
+ let entries = args.input.entries;
61
+ if (args.input.platform === "google" &&
62
+ ((_a = entries.find((entry) => entry.key === "credentials")) === null || _a === void 0 ? void 0 : _a.value) === "") {
63
+ const existing = await this.platformIntegrationService.getBaseSettings(ctx, "google");
64
+ const existingCredentials = (_b = existing === null || existing === void 0 ? void 0 : existing.entries.find((entry) => entry.key === "credentials")) === null || _b === void 0 ? void 0 : _b.value;
65
+ if (existingCredentials) {
66
+ entries = entries.map((entry) => entry.key === "credentials"
67
+ ? Object.assign(Object.assign({}, entry), { value: existingCredentials }) : entry);
68
+ }
69
+ }
64
70
  const settingsEntity = new platform_integration_settings_entity_js_1.MerchantPlatformSettingsEntity({
65
71
  platform: args.input.platform,
66
- entries: args.input.entries.map((entry) => new platform_integration_setting_entity_js_1.MerchantPlatformSetting(entry)),
72
+ entries: entries.map((entry) => new platform_integration_setting_entity_js_1.MerchantPlatformSetting(entry)),
67
73
  });
68
74
  if (settingsEntity.platform === "google") {
69
75
  this.googlePlatformIntegrationService.validateGoogleSettings(settingsEntity);
70
76
  }
71
77
  const settings = await this.platformIntegrationService.savePlatformIntegrationSettings(ctx, settingsEntity);
72
- return settings;
78
+ return settings ? this.redactCredentials(settings) : settings;
73
79
  }
74
80
  async removeOrphanItems(ctx, args) {
75
81
  return this.platformIntegrationService.removeOrphanItems(ctx, args.platform);
76
82
  }
83
+ redactCredentials(settings) {
84
+ return Object.assign(Object.assign({}, settings), { entries: settings.entries.map((entry) => entry.key === "credentials" ? Object.assign(Object.assign({}, entry), { value: "" }) : entry) });
85
+ }
77
86
  };
78
87
  exports.PlatformIntegrationAdminResolver = PlatformIntegrationAdminResolver;
79
88
  __decorate([
@@ -82,7 +91,7 @@ __decorate([
82
91
  __param(1, (0, graphql_1.Args)()),
83
92
  __metadata("design:type", Function),
84
93
  __metadata("design:paramtypes", [core_1.RequestContext, Object]),
85
- __metadata("design:returntype", void 0)
94
+ __metadata("design:returntype", Promise)
86
95
  ], PlatformIntegrationAdminResolver.prototype, "getMerchantPlatformSettings", null);
87
96
  __decorate([
88
97
  (0, graphql_1.Query)(),
@@ -92,6 +101,22 @@ __decorate([
92
101
  __metadata("design:paramtypes", [core_1.RequestContext, Object]),
93
102
  __metadata("design:returntype", Promise)
94
103
  ], PlatformIntegrationAdminResolver.prototype, "getMerchantPlatformInfo", null);
104
+ __decorate([
105
+ (0, graphql_1.Mutation)(),
106
+ __param(0, (0, core_1.Ctx)()),
107
+ __param(1, (0, graphql_1.Args)()),
108
+ __metadata("design:type", Function),
109
+ __metadata("design:paramtypes", [core_1.RequestContext, Object]),
110
+ __metadata("design:returntype", Promise)
111
+ ], PlatformIntegrationAdminResolver.prototype, "sendAllProductsToMerchantPlatform", null);
112
+ __decorate([
113
+ (0, graphql_1.Query)(),
114
+ __param(0, (0, core_1.Ctx)()),
115
+ __param(1, (0, graphql_1.Args)()),
116
+ __metadata("design:type", Function),
117
+ __metadata("design:paramtypes", [core_1.RequestContext, Object]),
118
+ __metadata("design:returntype", Promise)
119
+ ], PlatformIntegrationAdminResolver.prototype, "getMerchantSyncHistory", null);
95
120
  __decorate([
96
121
  (0, graphql_1.Mutation)(),
97
122
  __param(0, (0, core_1.Ctx)()),
@@ -0,0 +1,14 @@
1
+ import { DeepPartial } from "@deenruv/common/lib/shared-types.js";
2
+ import { DeenruvEntity } from "@deenruv/core";
3
+ import type { Relation } from "typeorm";
4
+ import { MerchantSyncRun } from "./merchant-sync-run.entity.js";
5
+ export declare class MerchantSyncItem extends DeenruvEntity {
6
+ constructor(input?: DeepPartial<MerchantSyncItem>);
7
+ offerId: string;
8
+ operation: string;
9
+ status: string;
10
+ errorCode: string | null;
11
+ errorMessage: string | null;
12
+ attempts: number;
13
+ run: Relation<MerchantSyncRun>;
14
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MerchantSyncItem = void 0;
13
+ const core_1 = require("@deenruv/core");
14
+ const typeorm_1 = require("typeorm");
15
+ const merchant_sync_run_entity_js_1 = require("./merchant-sync-run.entity.js");
16
+ let MerchantSyncItem = class MerchantSyncItem extends core_1.DeenruvEntity {
17
+ constructor(input) {
18
+ super(input);
19
+ }
20
+ };
21
+ exports.MerchantSyncItem = MerchantSyncItem;
22
+ __decorate([
23
+ (0, typeorm_1.Column)({ type: "varchar" }),
24
+ __metadata("design:type", String)
25
+ ], MerchantSyncItem.prototype, "offerId", void 0);
26
+ __decorate([
27
+ (0, typeorm_1.Column)({ type: "varchar" }),
28
+ __metadata("design:type", String)
29
+ ], MerchantSyncItem.prototype, "operation", void 0);
30
+ __decorate([
31
+ (0, typeorm_1.Column)({ type: "varchar" }),
32
+ __metadata("design:type", String)
33
+ ], MerchantSyncItem.prototype, "status", void 0);
34
+ __decorate([
35
+ (0, typeorm_1.Column)({ nullable: true, type: "varchar" }),
36
+ __metadata("design:type", Object)
37
+ ], MerchantSyncItem.prototype, "errorCode", void 0);
38
+ __decorate([
39
+ (0, typeorm_1.Column)({ type: "text", nullable: true }),
40
+ __metadata("design:type", Object)
41
+ ], MerchantSyncItem.prototype, "errorMessage", void 0);
42
+ __decorate([
43
+ (0, typeorm_1.Column)({ default: 1, type: "int" }),
44
+ __metadata("design:type", Number)
45
+ ], MerchantSyncItem.prototype, "attempts", void 0);
46
+ __decorate([
47
+ (0, typeorm_1.ManyToOne)(() => merchant_sync_run_entity_js_1.MerchantSyncRun, (run) => run.items, {
48
+ onDelete: "CASCADE",
49
+ }),
50
+ __metadata("design:type", Object)
51
+ ], MerchantSyncItem.prototype, "run", void 0);
52
+ exports.MerchantSyncItem = MerchantSyncItem = __decorate([
53
+ (0, typeorm_1.Entity)(),
54
+ (0, typeorm_1.Index)(["offerId", "createdAt"]),
55
+ __metadata("design:paramtypes", [Object])
56
+ ], MerchantSyncItem);
@@ -0,0 +1,19 @@
1
+ import { DeepPartial } from "@deenruv/common/lib/shared-types.js";
2
+ import { DeenruvEntity } from "@deenruv/core";
3
+ import type { Relation } from "typeorm";
4
+ import { MerchantSyncItem } from "./merchant-sync-item.entity.js";
5
+ export type MerchantSyncRunStatus = "PENDING" | "RUNNING" | "SUCCESS" | "PARTIAL" | "FAILED";
6
+ export declare class MerchantSyncRun extends DeenruvEntity {
7
+ constructor(input?: DeepPartial<MerchantSyncRun>);
8
+ platform: string;
9
+ trigger: string;
10
+ status: MerchantSyncRunStatus;
11
+ jobId: string | null;
12
+ total: number;
13
+ succeeded: number;
14
+ failed: number;
15
+ errorSummary: string | null;
16
+ startedAt: Date | null;
17
+ finishedAt: Date | null;
18
+ items: Relation<MerchantSyncItem[]>;
19
+ }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MerchantSyncRun = void 0;
13
+ const core_1 = require("@deenruv/core");
14
+ const typeorm_1 = require("typeorm");
15
+ const merchant_sync_item_entity_js_1 = require("./merchant-sync-item.entity.js");
16
+ let MerchantSyncRun = class MerchantSyncRun extends core_1.DeenruvEntity {
17
+ constructor(input) {
18
+ super(input);
19
+ }
20
+ };
21
+ exports.MerchantSyncRun = MerchantSyncRun;
22
+ __decorate([
23
+ (0, typeorm_1.Column)({ type: "varchar" }),
24
+ __metadata("design:type", String)
25
+ ], MerchantSyncRun.prototype, "platform", void 0);
26
+ __decorate([
27
+ (0, typeorm_1.Column)({ type: "varchar" }),
28
+ __metadata("design:type", String)
29
+ ], MerchantSyncRun.prototype, "trigger", void 0);
30
+ __decorate([
31
+ (0, typeorm_1.Column)({ default: "PENDING", type: "varchar" }),
32
+ __metadata("design:type", String)
33
+ ], MerchantSyncRun.prototype, "status", void 0);
34
+ __decorate([
35
+ (0, typeorm_1.Column)({ nullable: true, type: "varchar" }),
36
+ __metadata("design:type", Object)
37
+ ], MerchantSyncRun.prototype, "jobId", void 0);
38
+ __decorate([
39
+ (0, typeorm_1.Column)({ default: 0, type: "int" }),
40
+ __metadata("design:type", Number)
41
+ ], MerchantSyncRun.prototype, "total", void 0);
42
+ __decorate([
43
+ (0, typeorm_1.Column)({ default: 0, type: "int" }),
44
+ __metadata("design:type", Number)
45
+ ], MerchantSyncRun.prototype, "succeeded", void 0);
46
+ __decorate([
47
+ (0, typeorm_1.Column)({ default: 0, type: "int" }),
48
+ __metadata("design:type", Number)
49
+ ], MerchantSyncRun.prototype, "failed", void 0);
50
+ __decorate([
51
+ (0, typeorm_1.Column)({ type: "text", nullable: true }),
52
+ __metadata("design:type", Object)
53
+ ], MerchantSyncRun.prototype, "errorSummary", void 0);
54
+ __decorate([
55
+ (0, typeorm_1.Column)({ type: "timestamp", nullable: true }),
56
+ __metadata("design:type", Object)
57
+ ], MerchantSyncRun.prototype, "startedAt", void 0);
58
+ __decorate([
59
+ (0, typeorm_1.Column)({ type: "timestamp", nullable: true }),
60
+ __metadata("design:type", Object)
61
+ ], MerchantSyncRun.prototype, "finishedAt", void 0);
62
+ __decorate([
63
+ (0, typeorm_1.OneToMany)(() => merchant_sync_item_entity_js_1.MerchantSyncItem, (item) => item.run, {
64
+ cascade: true,
65
+ }),
66
+ __metadata("design:type", Object)
67
+ ], MerchantSyncRun.prototype, "items", void 0);
68
+ exports.MerchantSyncRun = MerchantSyncRun = __decorate([
69
+ (0, typeorm_1.Entity)(),
70
+ (0, typeorm_1.Index)(["platform", "createdAt"]),
71
+ __metadata("design:paramtypes", [Object])
72
+ ], MerchantSyncRun);
@@ -11,12 +11,59 @@ const base = (0, graphql_tag_1.gql) `
11
11
  type MerchantPlatformSettingsEntity implements Node {
12
12
  id: ID!
13
13
  platform: String!
14
- entries: [MerchantPlatformSetting!]
14
+ entries: [MerchantPlatformSetting!]!
15
15
  }
16
16
 
17
17
  type MerchantPlatformInfo {
18
18
  isValidConnection: Boolean!
19
19
  productsCount: Int!
20
+ connectionStatus: String
21
+ dataSourceVerified: Boolean
22
+ checkedAt: DateTime
23
+ latencyMs: Int
24
+ disapprovedProductsCount: Int
25
+ issuesCount: Int
26
+ lastError: MerchantPlatformError
27
+ issues: [MerchantProductIssue!]
28
+ }
29
+
30
+ type MerchantPlatformError {
31
+ code: String!
32
+ message: String!
33
+ retryable: Boolean!
34
+ }
35
+
36
+ type MerchantProductIssue {
37
+ offerId: String!
38
+ code: String!
39
+ description: String!
40
+ severity: String!
41
+ }
42
+
43
+ type MerchantSyncItem {
44
+ id: ID!
45
+ offerId: String!
46
+ operation: String!
47
+ status: String!
48
+ errorCode: String
49
+ errorMessage: String
50
+ attempts: Int!
51
+ }
52
+
53
+ type MerchantSyncRun {
54
+ id: ID!
55
+ createdAt: DateTime!
56
+ platform: String!
57
+ trigger: String!
58
+ status: String!
59
+ jobId: String
60
+ total: Int!
61
+ succeeded: Int!
62
+ failed: Int!
63
+ errorSummary: String
64
+ startedAt: DateTime
65
+ finishedAt: DateTime
66
+ items: [MerchantSyncItem!]!
20
67
  }
21
68
  `;
22
69
  exports.adminApiExtensions = (0, graphql_tag_1.gql) `
@@ -29,7 +76,7 @@ exports.adminApiExtensions = (0, graphql_tag_1.gql) `
29
76
 
30
77
  input SaveMerchantPlatformSettingInput {
31
78
  platform: String!
32
- entries: [MerchantPlatformSettingInput!]
79
+ entries: [MerchantPlatformSettingInput!]!
33
80
  }
34
81
 
35
82
  extend type Mutation {
@@ -45,5 +92,9 @@ exports.adminApiExtensions = (0, graphql_tag_1.gql) `
45
92
  platform: String!
46
93
  ): MerchantPlatformSettingsEntity
47
94
  getMerchantPlatformInfo(platform: String!): [MerchantPlatformInfo!]
95
+ getMerchantSyncHistory(
96
+ platform: String!
97
+ take: Int
98
+ ): [MerchantSyncRun!]!
48
99
  }
49
100
  `;
@@ -16,10 +16,13 @@ const platform_integration_admin_resolver_js_1 = require("./api/platform-integra
16
16
  const constants_js_1 = require("./constants.js");
17
17
  const platform_integration_setting_entity_js_1 = require("./entities/platform-integration-setting.entity.js");
18
18
  const platform_integration_settings_entity_js_1 = require("./entities/platform-integration-settings.entity.js");
19
+ const merchant_sync_item_entity_js_1 = require("./entities/merchant-sync-item.entity.js");
20
+ const merchant_sync_run_entity_js_1 = require("./entities/merchant-sync-run.entity.js");
19
21
  const api_extensions_js_1 = require("./extensions/api-extensions.js");
20
22
  const facebook_platform_integration_service_js_1 = require("./services/facebook-platform-integration.service.js");
21
23
  const google_platform_integration_service_js_1 = require("./services/google-platform-integration.service.js");
22
24
  const merchant_strategy_service_js_1 = require("./services/merchant-strategy.service.js");
25
+ const merchant_sync_history_service_js_1 = require("./services/merchant-sync-history.service.js");
23
26
  const platform_integration_service_js_1 = require("./services/platform-integration.service.js");
24
27
  const subscriber_service_js_1 = require("./services/subscriber.service.js");
25
28
  let MerchantPlugin = class MerchantPlugin {
@@ -56,7 +59,12 @@ exports.MerchantPlugin = MerchantPlugin = __decorate([
56
59
  (0, core_1.DeenruvPlugin)({
57
60
  compatibility: "^2.0.0",
58
61
  imports: [core_1.PluginCommonModule],
59
- entities: [platform_integration_setting_entity_js_1.MerchantPlatformSetting, platform_integration_settings_entity_js_1.MerchantPlatformSettingsEntity],
62
+ entities: [
63
+ platform_integration_setting_entity_js_1.MerchantPlatformSetting,
64
+ platform_integration_settings_entity_js_1.MerchantPlatformSettingsEntity,
65
+ merchant_sync_run_entity_js_1.MerchantSyncRun,
66
+ merchant_sync_item_entity_js_1.MerchantSyncItem,
67
+ ],
60
68
  shopApiExtensions: {},
61
69
  adminApiExtensions: {
62
70
  schema: api_extensions_js_1.adminApiExtensions,
@@ -68,6 +76,7 @@ exports.MerchantPlugin = MerchantPlugin = __decorate([
68
76
  useFactory: () => MerchantPlugin.options,
69
77
  },
70
78
  merchant_strategy_service_js_1.MerchantStrategyService,
79
+ merchant_sync_history_service_js_1.MerchantSyncHistoryService,
71
80
  platform_integration_service_js_1.PlatformIntegrationService,
72
81
  google_platform_integration_service_js_1.GooglePlatformIntegrationService,
73
82
  facebook_platform_integration_service_js_1.FacebookPlatformIntegrationService,
@@ -1,4 +1,5 @@
1
1
  import { v1 } from "@google-shopping/products";
2
+ import { v1 as dataSourcesV1 } from "@google-shopping/datasources";
2
3
  import type { protos } from "@google-shopping/products";
3
4
  import type { GoogleProcessedProduct, GoogleProduct, GoogleProductInput, RemoteProduct } from "../types.js";
4
5
  export declare const GOOGLE_CONTENT_LANGUAGE = "pl";
@@ -12,8 +13,11 @@ export type GoogleMerchantSettings = {
12
13
  brand: string;
13
14
  credentials: GoogleMerchantCredentials;
14
15
  dataSource: string;
16
+ contentLanguage: string;
17
+ feedLabel: string;
15
18
  };
16
19
  export type GoogleMerchantClients = {
20
+ dataSources: dataSourcesV1.DataSourcesServiceClient;
17
21
  productInputs: v1.ProductInputsServiceClient;
18
22
  products: v1.ProductsServiceClient;
19
23
  };
@@ -35,10 +39,12 @@ export type GoogleWriteOperation = {
35
39
  request: DeleteProductInputRequest;
36
40
  };
37
41
  export type MerchantOperationResult<T> = {
42
+ attempts: number;
38
43
  index: number;
39
44
  item: T;
40
45
  status: "success";
41
46
  } | {
47
+ attempts: number;
42
48
  error: unknown;
43
49
  index: number;
44
50
  item: T;
@@ -59,26 +65,62 @@ export interface GoogleProductInputsWriter {
59
65
  export interface GoogleProductsReader {
60
66
  listProductsAsync(request: ListProductsRequest): AsyncIterable<GoogleProcessedProduct>;
61
67
  }
68
+ export interface GoogleDataSourcesReader {
69
+ getDataSource(request: {
70
+ name: string;
71
+ }): Promise<unknown>;
72
+ }
73
+ export type GoogleMerchantRetryOptions = {
74
+ delay?: (attempt: number) => Promise<void>;
75
+ maxAttempts?: number;
76
+ };
77
+ export type GoogleMerchantConnectionStatus = "CONNECTED" | "NOT_CONFIGURED" | "INVALID_CONFIGURATION" | "DATA_SOURCE_NOT_FOUND" | "AUTHENTICATION_FAILED" | "PERMISSION_DENIED" | "UNAVAILABLE" | "ERROR";
78
+ export type GoogleMerchantProductIssue = {
79
+ code: string;
80
+ description: string;
81
+ offerId: string;
82
+ severity: string;
83
+ };
84
+ export type GoogleMerchantConnectionDiagnostic = {
85
+ checkedAt: string;
86
+ connectionStatus: GoogleMerchantConnectionStatus;
87
+ dataSourceVerified: boolean;
88
+ disapprovedProductsCount: number;
89
+ issues: GoogleMerchantProductIssue[];
90
+ issuesCount: number;
91
+ lastError?: Omit<NormalizedGoogleMerchantError, "status">;
92
+ latencyMs: number;
93
+ productsCount: number;
94
+ };
95
+ export type NormalizedGoogleMerchantError = {
96
+ code: string;
97
+ message: string;
98
+ retryable: boolean;
99
+ status: GoogleMerchantConnectionStatus;
100
+ };
62
101
  type SettingEntry = {
63
102
  key: string;
64
103
  value: string;
65
104
  };
105
+ export declare function normalizeGoogleMerchantError(error: unknown): NormalizedGoogleMerchantError;
66
106
  export declare function parseGoogleCredentials(rawCredentials: string): GoogleMerchantCredentials;
67
107
  export declare function normalizeMerchantId(rawMerchantId: string): string;
68
108
  export declare function normalizeDataSource(rawDataSource: string, merchantId: string): string;
69
109
  export declare function parseGoogleMerchantSettings(entries: readonly SettingEntry[]): GoogleMerchantSettings;
70
110
  export declare function createGoogleMerchantClients(credentials: GoogleMerchantCredentials): GoogleMerchantClients;
71
- export declare function buildGoogleProductIdentifier(offerId: string): string;
72
- export declare function buildGoogleProductName(accountId: string, offerId: string): string;
73
- export declare function buildGoogleProductInputName(accountId: string, offerId: string): string;
74
- export declare function toGoogleProductInput(product: GoogleProduct, brand: string): GoogleProductInput;
111
+ export declare function buildGoogleProductIdentifier(offerId: string, contentLanguage?: string, feedLabel?: string): string;
112
+ export declare function buildGoogleProductName(accountId: string, offerId: string, contentLanguage?: string, feedLabel?: string): string;
113
+ export declare function buildGoogleProductInputName(accountId: string, offerId: string, contentLanguage?: string, feedLabel?: string): string;
114
+ export declare function toGoogleProductInput(product: GoogleProduct, brand: string, contentLanguage?: string, feedLabel?: string): GoogleProductInput;
115
+ export declare function validateGoogleProductUrls(product: GoogleProduct): void;
75
116
  export declare function buildGoogleUpdateMask(productInput: GoogleProductInput): protos.google.protobuf.IFieldMask;
76
117
  export declare function createGoogleInsertOperation(product: GoogleProduct, settings: GoogleMerchantSettings): GoogleWriteOperation;
77
118
  export declare function createGoogleUpdateOperation(product: GoogleProduct, settings: GoogleMerchantSettings): GoogleWriteOperation;
78
119
  export declare function createGoogleDeleteOperation(communicateID: string, settings: GoogleMerchantSettings): GoogleWriteOperation;
79
- export declare function runBoundedMerchantOperations<T>(items: readonly T[], operation: (item: T, index: number) => Promise<void>, concurrency?: number): Promise<Array<MerchantOperationResult<T>>>;
80
- export declare function executeGoogleWriteOperations(client: GoogleProductInputsWriter, operations: readonly GoogleWriteOperation[], concurrency?: number): Promise<Array<MerchantOperationResult<GoogleWriteOperation>>>;
120
+ export declare function runBoundedMerchantOperations<T>(items: readonly T[], operation: (item: T, index: number) => Promise<number | void>, concurrency?: number): Promise<Array<MerchantOperationResult<T>>>;
121
+ export declare function executeGoogleWriteOperations(client: GoogleProductInputsWriter, operations: readonly GoogleWriteOperation[], concurrency?: number, retryOptions?: GoogleMerchantRetryOptions): Promise<Array<MerchantOperationResult<GoogleWriteOperation>>>;
81
122
  export declare function summarizeMerchantOperations<T>(results: Array<MerchantOperationResult<T>>): MerchantOperationSummary<T>;
82
123
  export declare function collectGoogleProductsForDataSource(client: GoogleProductsReader, accountId: string, dataSource: string): Promise<RemoteProduct[]>;
124
+ export declare function diagnoseGoogleMerchantConnection(client: GoogleProductsReader, settings: Pick<GoogleMerchantSettings, "accountId" | "dataSource">, dataSourcesClient?: GoogleDataSourcesReader): Promise<GoogleMerchantConnectionDiagnostic>;
83
125
  export declare function selectRemoteOrphanProducts(remoteProducts: readonly RemoteProduct[], localProducts: readonly Pick<GoogleProduct, "communicateID">[]): RemoteProduct[];
84
126
  export {};