@progus/connector 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-WZ5FAA44.js +129 -0
- package/dist/crossSell-BFz9e72n.d.cts +78 -0
- package/dist/crossSell-BFz9e72n.d.ts +78 -0
- package/dist/crossSell.cjs +144 -0
- package/dist/crossSell.d.cts +1 -0
- package/dist/crossSell.d.ts +1 -0
- package/dist/crossSell.js +10 -0
- package/dist/index.d.cts +3 -77
- package/dist/index.d.ts +3 -77
- package/dist/index.js +10 -120
- package/package.json +8 -3
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/utils.ts
|
|
2
|
+
function normalizePartnerId(value) {
|
|
3
|
+
if (!value) return null;
|
|
4
|
+
const trimmed = value.trim();
|
|
5
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
6
|
+
}
|
|
7
|
+
function buildEventId(shopDomain, eventName, externalId) {
|
|
8
|
+
if (!externalId) return void 0;
|
|
9
|
+
return `${shopDomain}:${eventName}:${externalId}`;
|
|
10
|
+
}
|
|
11
|
+
function stripTrailingSlash(value) {
|
|
12
|
+
return value.replace(/\/+$/, "");
|
|
13
|
+
}
|
|
14
|
+
function safeJsonParse(text) {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(text);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/crossSell.ts
|
|
23
|
+
function getCrossSellOffers(options = {}) {
|
|
24
|
+
const appsCatalog = options.appsCatalog ?? [];
|
|
25
|
+
const installedKeys = new Set(
|
|
26
|
+
[options.appName, ...options.installedAppKeys ?? []].filter(
|
|
27
|
+
(key) => Boolean(key)
|
|
28
|
+
)
|
|
29
|
+
);
|
|
30
|
+
const locale = options.locale;
|
|
31
|
+
return appsCatalog.filter((app) => app.enabled !== false).filter((app) => locale ? !app.locales || app.locales.includes(locale) : true).filter((app) => !installedKeys.has(app.key)).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
32
|
+
}
|
|
33
|
+
var DEFAULT_APPS_CATALOG_URL = "https://appsdata.progus.com/recommendations";
|
|
34
|
+
var FALLBACK_APPS_CATALOG = [
|
|
35
|
+
{
|
|
36
|
+
key: "progus_ai_studio",
|
|
37
|
+
type: "app",
|
|
38
|
+
title: "Progus AI Studio",
|
|
39
|
+
company: "Progus",
|
|
40
|
+
companyUrl: "https://progus.com",
|
|
41
|
+
desc: "Generate on-brand AI product & variant images in bulk.",
|
|
42
|
+
url: "https://apps.shopify.com/progus-ai-studio",
|
|
43
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/9428a41ed53c66cd7329a2583cd2f3d9/icon/COje1rnS4pEDEAE=.png",
|
|
44
|
+
priority: 100,
|
|
45
|
+
enabled: true
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
key: "progus_trust_badges",
|
|
49
|
+
type: "app",
|
|
50
|
+
title: "Progus Trust Badges",
|
|
51
|
+
company: "Progus",
|
|
52
|
+
companyUrl: "https://progus.com",
|
|
53
|
+
desc: "Add Trust Badges to your store to build trust and credibility.",
|
|
54
|
+
url: "https://apps.shopify.com/progus-trust-badges-1",
|
|
55
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/f9d0009e237f27d2db35b41ef99be858/icon/CJ3y1qDn1JEDEAE=.png",
|
|
56
|
+
priority: 80,
|
|
57
|
+
enabled: true
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "progus_cod",
|
|
61
|
+
type: "app",
|
|
62
|
+
title: "Progus COD",
|
|
63
|
+
company: "Progus",
|
|
64
|
+
companyUrl: "https://progus.com",
|
|
65
|
+
desc: "Automate COD Fees & Hide/Show Cash on Delivery by Rules.",
|
|
66
|
+
url: "https://apps.shopify.com/progus-cod",
|
|
67
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/bc537219cc3ed2bd4e7e3e683fe6b74a/icon/CMi_6dTEkIoDEAE=.png",
|
|
68
|
+
priority: 90,
|
|
69
|
+
enabled: true
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
function buildFallbackCatalog(options) {
|
|
73
|
+
const appName = options.appName;
|
|
74
|
+
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
75
|
+
let items = FALLBACK_APPS_CATALOG.filter((app) => app.enabled !== false);
|
|
76
|
+
if (appName) {
|
|
77
|
+
items = items.filter((app) => app.key !== appName);
|
|
78
|
+
}
|
|
79
|
+
if (limit > 0) {
|
|
80
|
+
items = items.slice(0, limit);
|
|
81
|
+
}
|
|
82
|
+
return items;
|
|
83
|
+
}
|
|
84
|
+
async function fetchAppsCatalog(options = {}) {
|
|
85
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
86
|
+
const logger = options.logger ?? console;
|
|
87
|
+
const appName = options.appName;
|
|
88
|
+
const baseUrl = stripTrailingSlash(options.appsCatalogUrl ?? DEFAULT_APPS_CATALOG_URL);
|
|
89
|
+
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
90
|
+
const params = new URLSearchParams();
|
|
91
|
+
if (appName) params.set("appName", appName);
|
|
92
|
+
if (limit > 0) params.set("limit", String(limit));
|
|
93
|
+
const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
|
|
94
|
+
if (!fetchImpl) {
|
|
95
|
+
logger?.error?.("Failed to fetch apps catalog", {
|
|
96
|
+
error: "Fetch implementation is required"
|
|
97
|
+
});
|
|
98
|
+
return buildFallbackCatalog(options);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const response = await fetchImpl(url);
|
|
102
|
+
const text = await response.text();
|
|
103
|
+
const parsed = safeJsonParse(text);
|
|
104
|
+
if (!response.ok || !parsed) {
|
|
105
|
+
logger?.error?.("Failed to fetch apps catalog", { status: response.status });
|
|
106
|
+
return buildFallbackCatalog(options);
|
|
107
|
+
}
|
|
108
|
+
return parsed;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
logger?.error?.("Failed to fetch apps catalog", {
|
|
111
|
+
error: error instanceof Error ? error.message : String(error)
|
|
112
|
+
});
|
|
113
|
+
return buildFallbackCatalog(options);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function getCrossSellOffersFromApi(options = {}) {
|
|
117
|
+
const appsCatalog = options.appsCatalog ?? await fetchAppsCatalog(options);
|
|
118
|
+
return getCrossSellOffers({ ...options, appsCatalog });
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export {
|
|
122
|
+
normalizePartnerId,
|
|
123
|
+
buildEventId,
|
|
124
|
+
stripTrailingSlash,
|
|
125
|
+
safeJsonParse,
|
|
126
|
+
getCrossSellOffers,
|
|
127
|
+
fetchAppsCatalog,
|
|
128
|
+
getCrossSellOffersFromApi
|
|
129
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
type Logger = {
|
|
2
|
+
info?: (message: string, meta?: Record<string, unknown>) => void;
|
|
3
|
+
warn?: (message: string, meta?: Record<string, unknown>) => void;
|
|
4
|
+
error?: (message: string, meta?: Record<string, unknown>) => void;
|
|
5
|
+
};
|
|
6
|
+
type FetchLike = typeof fetch;
|
|
7
|
+
type ConnectorConfig = {
|
|
8
|
+
appKey: string;
|
|
9
|
+
apiBaseUrl: string;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
signingSecret?: string;
|
|
12
|
+
fetch?: FetchLike;
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
enableIdempotency?: boolean;
|
|
15
|
+
};
|
|
16
|
+
type TrackEventName = "installation" | "uninstallation" | "subscription";
|
|
17
|
+
type TrackEventParams<TData = Record<string, unknown>> = {
|
|
18
|
+
eventName: TrackEventName | (string & {});
|
|
19
|
+
shopDomain: string;
|
|
20
|
+
partnerId?: string | null;
|
|
21
|
+
data?: TData;
|
|
22
|
+
externalId?: string;
|
|
23
|
+
};
|
|
24
|
+
type TrackResult<TData = Record<string, unknown>> = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
message?: string;
|
|
27
|
+
status?: number;
|
|
28
|
+
data?: TData;
|
|
29
|
+
};
|
|
30
|
+
type CheckPartnerIdResult = {
|
|
31
|
+
success: boolean;
|
|
32
|
+
partnerId?: string;
|
|
33
|
+
message?: string;
|
|
34
|
+
status?: number;
|
|
35
|
+
};
|
|
36
|
+
type AssignPartnerIdInput = {
|
|
37
|
+
shopDomain: string;
|
|
38
|
+
partnerId: string;
|
|
39
|
+
};
|
|
40
|
+
type SubscriptionEventData = {
|
|
41
|
+
subscriptionStatus?: string;
|
|
42
|
+
subscriptionName?: string;
|
|
43
|
+
subscriptionId?: number | string;
|
|
44
|
+
subscriptionPrice?: number | string;
|
|
45
|
+
subscriptionPeriod?: string;
|
|
46
|
+
};
|
|
47
|
+
type AppsCatalogEntry = {
|
|
48
|
+
key: string;
|
|
49
|
+
type: string;
|
|
50
|
+
title: string;
|
|
51
|
+
company?: string;
|
|
52
|
+
companyUrl?: string;
|
|
53
|
+
desc?: string;
|
|
54
|
+
url: string;
|
|
55
|
+
icon?: string;
|
|
56
|
+
enabled?: boolean;
|
|
57
|
+
priority?: number;
|
|
58
|
+
locales?: string[];
|
|
59
|
+
};
|
|
60
|
+
type CrossSellOptions = {
|
|
61
|
+
appName?: string;
|
|
62
|
+
installedAppKeys?: string[];
|
|
63
|
+
locale?: string;
|
|
64
|
+
shopPlan?: string;
|
|
65
|
+
appsCatalog?: AppsCatalogEntry[];
|
|
66
|
+
};
|
|
67
|
+
type CrossSellFetchOptions = CrossSellOptions & {
|
|
68
|
+
appsCatalogUrl?: string;
|
|
69
|
+
limit?: number;
|
|
70
|
+
fetch?: FetchLike;
|
|
71
|
+
logger?: Logger;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare function getCrossSellOffers(options?: CrossSellOptions): AppsCatalogEntry[];
|
|
75
|
+
declare function fetchAppsCatalog(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
76
|
+
declare function getCrossSellOffersFromApi(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
77
|
+
|
|
78
|
+
export { type AssignPartnerIdInput as A, type ConnectorConfig as C, type Logger as L, type SubscriptionEventData as S, type TrackEventParams as T, type TrackResult as a, type CheckPartnerIdResult as b, getCrossSellOffersFromApi as c, type AppsCatalogEntry as d, type CrossSellFetchOptions as e, fetchAppsCatalog as f, getCrossSellOffers as g, type CrossSellOptions as h, type TrackEventName as i };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
type Logger = {
|
|
2
|
+
info?: (message: string, meta?: Record<string, unknown>) => void;
|
|
3
|
+
warn?: (message: string, meta?: Record<string, unknown>) => void;
|
|
4
|
+
error?: (message: string, meta?: Record<string, unknown>) => void;
|
|
5
|
+
};
|
|
6
|
+
type FetchLike = typeof fetch;
|
|
7
|
+
type ConnectorConfig = {
|
|
8
|
+
appKey: string;
|
|
9
|
+
apiBaseUrl: string;
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
signingSecret?: string;
|
|
12
|
+
fetch?: FetchLike;
|
|
13
|
+
logger?: Logger;
|
|
14
|
+
enableIdempotency?: boolean;
|
|
15
|
+
};
|
|
16
|
+
type TrackEventName = "installation" | "uninstallation" | "subscription";
|
|
17
|
+
type TrackEventParams<TData = Record<string, unknown>> = {
|
|
18
|
+
eventName: TrackEventName | (string & {});
|
|
19
|
+
shopDomain: string;
|
|
20
|
+
partnerId?: string | null;
|
|
21
|
+
data?: TData;
|
|
22
|
+
externalId?: string;
|
|
23
|
+
};
|
|
24
|
+
type TrackResult<TData = Record<string, unknown>> = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
message?: string;
|
|
27
|
+
status?: number;
|
|
28
|
+
data?: TData;
|
|
29
|
+
};
|
|
30
|
+
type CheckPartnerIdResult = {
|
|
31
|
+
success: boolean;
|
|
32
|
+
partnerId?: string;
|
|
33
|
+
message?: string;
|
|
34
|
+
status?: number;
|
|
35
|
+
};
|
|
36
|
+
type AssignPartnerIdInput = {
|
|
37
|
+
shopDomain: string;
|
|
38
|
+
partnerId: string;
|
|
39
|
+
};
|
|
40
|
+
type SubscriptionEventData = {
|
|
41
|
+
subscriptionStatus?: string;
|
|
42
|
+
subscriptionName?: string;
|
|
43
|
+
subscriptionId?: number | string;
|
|
44
|
+
subscriptionPrice?: number | string;
|
|
45
|
+
subscriptionPeriod?: string;
|
|
46
|
+
};
|
|
47
|
+
type AppsCatalogEntry = {
|
|
48
|
+
key: string;
|
|
49
|
+
type: string;
|
|
50
|
+
title: string;
|
|
51
|
+
company?: string;
|
|
52
|
+
companyUrl?: string;
|
|
53
|
+
desc?: string;
|
|
54
|
+
url: string;
|
|
55
|
+
icon?: string;
|
|
56
|
+
enabled?: boolean;
|
|
57
|
+
priority?: number;
|
|
58
|
+
locales?: string[];
|
|
59
|
+
};
|
|
60
|
+
type CrossSellOptions = {
|
|
61
|
+
appName?: string;
|
|
62
|
+
installedAppKeys?: string[];
|
|
63
|
+
locale?: string;
|
|
64
|
+
shopPlan?: string;
|
|
65
|
+
appsCatalog?: AppsCatalogEntry[];
|
|
66
|
+
};
|
|
67
|
+
type CrossSellFetchOptions = CrossSellOptions & {
|
|
68
|
+
appsCatalogUrl?: string;
|
|
69
|
+
limit?: number;
|
|
70
|
+
fetch?: FetchLike;
|
|
71
|
+
logger?: Logger;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
declare function getCrossSellOffers(options?: CrossSellOptions): AppsCatalogEntry[];
|
|
75
|
+
declare function fetchAppsCatalog(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
76
|
+
declare function getCrossSellOffersFromApi(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
77
|
+
|
|
78
|
+
export { type AssignPartnerIdInput as A, type ConnectorConfig as C, type Logger as L, type SubscriptionEventData as S, type TrackEventParams as T, type TrackResult as a, type CheckPartnerIdResult as b, getCrossSellOffersFromApi as c, type AppsCatalogEntry as d, type CrossSellFetchOptions as e, fetchAppsCatalog as f, getCrossSellOffers as g, type CrossSellOptions as h, type TrackEventName as i };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/crossSell.ts
|
|
21
|
+
var crossSell_exports = {};
|
|
22
|
+
__export(crossSell_exports, {
|
|
23
|
+
fetchAppsCatalog: () => fetchAppsCatalog,
|
|
24
|
+
getCrossSellOffers: () => getCrossSellOffers,
|
|
25
|
+
getCrossSellOffersFromApi: () => getCrossSellOffersFromApi
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(crossSell_exports);
|
|
28
|
+
|
|
29
|
+
// src/utils.ts
|
|
30
|
+
function stripTrailingSlash(value) {
|
|
31
|
+
return value.replace(/\/+$/, "");
|
|
32
|
+
}
|
|
33
|
+
function safeJsonParse(text) {
|
|
34
|
+
try {
|
|
35
|
+
return JSON.parse(text);
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/crossSell.ts
|
|
42
|
+
function getCrossSellOffers(options = {}) {
|
|
43
|
+
const appsCatalog = options.appsCatalog ?? [];
|
|
44
|
+
const installedKeys = new Set(
|
|
45
|
+
[options.appName, ...options.installedAppKeys ?? []].filter(
|
|
46
|
+
(key) => Boolean(key)
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
const locale = options.locale;
|
|
50
|
+
return appsCatalog.filter((app) => app.enabled !== false).filter((app) => locale ? !app.locales || app.locales.includes(locale) : true).filter((app) => !installedKeys.has(app.key)).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
51
|
+
}
|
|
52
|
+
var DEFAULT_APPS_CATALOG_URL = "https://appsdata.progus.com/recommendations";
|
|
53
|
+
var FALLBACK_APPS_CATALOG = [
|
|
54
|
+
{
|
|
55
|
+
key: "progus_ai_studio",
|
|
56
|
+
type: "app",
|
|
57
|
+
title: "Progus AI Studio",
|
|
58
|
+
company: "Progus",
|
|
59
|
+
companyUrl: "https://progus.com",
|
|
60
|
+
desc: "Generate on-brand AI product & variant images in bulk.",
|
|
61
|
+
url: "https://apps.shopify.com/progus-ai-studio",
|
|
62
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/9428a41ed53c66cd7329a2583cd2f3d9/icon/COje1rnS4pEDEAE=.png",
|
|
63
|
+
priority: 100,
|
|
64
|
+
enabled: true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: "progus_trust_badges",
|
|
68
|
+
type: "app",
|
|
69
|
+
title: "Progus Trust Badges",
|
|
70
|
+
company: "Progus",
|
|
71
|
+
companyUrl: "https://progus.com",
|
|
72
|
+
desc: "Add Trust Badges to your store to build trust and credibility.",
|
|
73
|
+
url: "https://apps.shopify.com/progus-trust-badges-1",
|
|
74
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/f9d0009e237f27d2db35b41ef99be858/icon/CJ3y1qDn1JEDEAE=.png",
|
|
75
|
+
priority: 80,
|
|
76
|
+
enabled: true
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
key: "progus_cod",
|
|
80
|
+
type: "app",
|
|
81
|
+
title: "Progus COD",
|
|
82
|
+
company: "Progus",
|
|
83
|
+
companyUrl: "https://progus.com",
|
|
84
|
+
desc: "Automate COD Fees & Hide/Show Cash on Delivery by Rules.",
|
|
85
|
+
url: "https://apps.shopify.com/progus-cod",
|
|
86
|
+
icon: "https://cdn.shopify.com/app-store/listing_images/bc537219cc3ed2bd4e7e3e683fe6b74a/icon/CMi_6dTEkIoDEAE=.png",
|
|
87
|
+
priority: 90,
|
|
88
|
+
enabled: true
|
|
89
|
+
}
|
|
90
|
+
];
|
|
91
|
+
function buildFallbackCatalog(options) {
|
|
92
|
+
const appName = options.appName;
|
|
93
|
+
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
94
|
+
let items = FALLBACK_APPS_CATALOG.filter((app) => app.enabled !== false);
|
|
95
|
+
if (appName) {
|
|
96
|
+
items = items.filter((app) => app.key !== appName);
|
|
97
|
+
}
|
|
98
|
+
if (limit > 0) {
|
|
99
|
+
items = items.slice(0, limit);
|
|
100
|
+
}
|
|
101
|
+
return items;
|
|
102
|
+
}
|
|
103
|
+
async function fetchAppsCatalog(options = {}) {
|
|
104
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
105
|
+
const logger = options.logger ?? console;
|
|
106
|
+
const appName = options.appName;
|
|
107
|
+
const baseUrl = stripTrailingSlash(options.appsCatalogUrl ?? DEFAULT_APPS_CATALOG_URL);
|
|
108
|
+
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
109
|
+
const params = new URLSearchParams();
|
|
110
|
+
if (appName) params.set("appName", appName);
|
|
111
|
+
if (limit > 0) params.set("limit", String(limit));
|
|
112
|
+
const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
|
|
113
|
+
if (!fetchImpl) {
|
|
114
|
+
logger?.error?.("Failed to fetch apps catalog", {
|
|
115
|
+
error: "Fetch implementation is required"
|
|
116
|
+
});
|
|
117
|
+
return buildFallbackCatalog(options);
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const response = await fetchImpl(url);
|
|
121
|
+
const text = await response.text();
|
|
122
|
+
const parsed = safeJsonParse(text);
|
|
123
|
+
if (!response.ok || !parsed) {
|
|
124
|
+
logger?.error?.("Failed to fetch apps catalog", { status: response.status });
|
|
125
|
+
return buildFallbackCatalog(options);
|
|
126
|
+
}
|
|
127
|
+
return parsed;
|
|
128
|
+
} catch (error) {
|
|
129
|
+
logger?.error?.("Failed to fetch apps catalog", {
|
|
130
|
+
error: error instanceof Error ? error.message : String(error)
|
|
131
|
+
});
|
|
132
|
+
return buildFallbackCatalog(options);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async function getCrossSellOffersFromApi(options = {}) {
|
|
136
|
+
const appsCatalog = options.appsCatalog ?? await fetchAppsCatalog(options);
|
|
137
|
+
return getCrossSellOffers({ ...options, appsCatalog });
|
|
138
|
+
}
|
|
139
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
140
|
+
0 && (module.exports = {
|
|
141
|
+
fetchAppsCatalog,
|
|
142
|
+
getCrossSellOffers,
|
|
143
|
+
getCrossSellOffersFromApi
|
|
144
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { f as fetchAppsCatalog, g as getCrossSellOffers, c as getCrossSellOffersFromApi } from './crossSell-BFz9e72n.cjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { f as fetchAppsCatalog, g as getCrossSellOffers, c as getCrossSellOffersFromApi } from './crossSell-BFz9e72n.js';
|
package/dist/index.d.cts
CHANGED
|
@@ -1,75 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
warn?: (message: string, meta?: Record<string, unknown>) => void;
|
|
4
|
-
error?: (message: string, meta?: Record<string, unknown>) => void;
|
|
5
|
-
};
|
|
6
|
-
type FetchLike = typeof fetch;
|
|
7
|
-
type ConnectorConfig = {
|
|
8
|
-
appKey: string;
|
|
9
|
-
apiBaseUrl: string;
|
|
10
|
-
apiKey?: string;
|
|
11
|
-
signingSecret?: string;
|
|
12
|
-
fetch?: FetchLike;
|
|
13
|
-
logger?: Logger;
|
|
14
|
-
enableIdempotency?: boolean;
|
|
15
|
-
};
|
|
16
|
-
type TrackEventName = "installation" | "uninstallation" | "subscription";
|
|
17
|
-
type TrackEventParams<TData = Record<string, unknown>> = {
|
|
18
|
-
eventName: TrackEventName | (string & {});
|
|
19
|
-
shopDomain: string;
|
|
20
|
-
partnerId?: string | null;
|
|
21
|
-
data?: TData;
|
|
22
|
-
externalId?: string;
|
|
23
|
-
};
|
|
24
|
-
type TrackResult<TData = Record<string, unknown>> = {
|
|
25
|
-
success: boolean;
|
|
26
|
-
message?: string;
|
|
27
|
-
status?: number;
|
|
28
|
-
data?: TData;
|
|
29
|
-
};
|
|
30
|
-
type CheckPartnerIdResult = {
|
|
31
|
-
success: boolean;
|
|
32
|
-
partnerId?: string;
|
|
33
|
-
message?: string;
|
|
34
|
-
status?: number;
|
|
35
|
-
};
|
|
36
|
-
type AssignPartnerIdInput = {
|
|
37
|
-
shopDomain: string;
|
|
38
|
-
partnerId: string;
|
|
39
|
-
};
|
|
40
|
-
type SubscriptionEventData = {
|
|
41
|
-
subscriptionStatus?: string;
|
|
42
|
-
subscriptionName?: string;
|
|
43
|
-
subscriptionId?: number | string;
|
|
44
|
-
subscriptionPrice?: number | string;
|
|
45
|
-
subscriptionPeriod?: string;
|
|
46
|
-
};
|
|
47
|
-
type AppsCatalogEntry = {
|
|
48
|
-
key: string;
|
|
49
|
-
type: string;
|
|
50
|
-
title: string;
|
|
51
|
-
company?: string;
|
|
52
|
-
companyUrl?: string;
|
|
53
|
-
desc?: string;
|
|
54
|
-
url: string;
|
|
55
|
-
icon?: string;
|
|
56
|
-
enabled?: boolean;
|
|
57
|
-
priority?: number;
|
|
58
|
-
locales?: string[];
|
|
59
|
-
};
|
|
60
|
-
type CrossSellOptions = {
|
|
61
|
-
appName?: string;
|
|
62
|
-
installedAppKeys?: string[];
|
|
63
|
-
locale?: string;
|
|
64
|
-
shopPlan?: string;
|
|
65
|
-
appsCatalog?: AppsCatalogEntry[];
|
|
66
|
-
};
|
|
67
|
-
type CrossSellFetchOptions = CrossSellOptions & {
|
|
68
|
-
appsCatalogUrl?: string;
|
|
69
|
-
limit?: number;
|
|
70
|
-
fetch?: FetchLike;
|
|
71
|
-
logger?: Logger;
|
|
72
|
-
};
|
|
1
|
+
import { C as ConnectorConfig, T as TrackEventParams, a as TrackResult, S as SubscriptionEventData, A as AssignPartnerIdInput, b as CheckPartnerIdResult } from './crossSell-BFz9e72n.cjs';
|
|
2
|
+
export { d as AppsCatalogEntry, e as CrossSellFetchOptions, h as CrossSellOptions, L as Logger, i as TrackEventName, f as fetchAppsCatalog, g as getCrossSellOffers, c as getCrossSellOffersFromApi } from './crossSell-BFz9e72n.cjs';
|
|
73
3
|
|
|
74
4
|
type Connector = {
|
|
75
5
|
track: (eventName: TrackEventParams["eventName"], payload: Omit<TrackEventParams, "eventName">) => Promise<TrackResult>;
|
|
@@ -101,12 +31,8 @@ type Connector = {
|
|
|
101
31
|
};
|
|
102
32
|
declare function createProgusConnector(config: ConnectorConfig): Connector;
|
|
103
33
|
|
|
104
|
-
declare function getCrossSellOffers(options?: CrossSellOptions): AppsCatalogEntry[];
|
|
105
|
-
declare function fetchAppsCatalog(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
106
|
-
declare function getCrossSellOffersFromApi(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
107
|
-
|
|
108
34
|
declare function signPayload(body: string, secret: string): string;
|
|
109
35
|
|
|
110
36
|
declare function normalizePartnerId(value?: string | null): string | null;
|
|
111
37
|
|
|
112
|
-
export {
|
|
38
|
+
export { AssignPartnerIdInput, CheckPartnerIdResult, ConnectorConfig, SubscriptionEventData, TrackEventParams, TrackResult, createProgusConnector, normalizePartnerId, signPayload };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,75 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
warn?: (message: string, meta?: Record<string, unknown>) => void;
|
|
4
|
-
error?: (message: string, meta?: Record<string, unknown>) => void;
|
|
5
|
-
};
|
|
6
|
-
type FetchLike = typeof fetch;
|
|
7
|
-
type ConnectorConfig = {
|
|
8
|
-
appKey: string;
|
|
9
|
-
apiBaseUrl: string;
|
|
10
|
-
apiKey?: string;
|
|
11
|
-
signingSecret?: string;
|
|
12
|
-
fetch?: FetchLike;
|
|
13
|
-
logger?: Logger;
|
|
14
|
-
enableIdempotency?: boolean;
|
|
15
|
-
};
|
|
16
|
-
type TrackEventName = "installation" | "uninstallation" | "subscription";
|
|
17
|
-
type TrackEventParams<TData = Record<string, unknown>> = {
|
|
18
|
-
eventName: TrackEventName | (string & {});
|
|
19
|
-
shopDomain: string;
|
|
20
|
-
partnerId?: string | null;
|
|
21
|
-
data?: TData;
|
|
22
|
-
externalId?: string;
|
|
23
|
-
};
|
|
24
|
-
type TrackResult<TData = Record<string, unknown>> = {
|
|
25
|
-
success: boolean;
|
|
26
|
-
message?: string;
|
|
27
|
-
status?: number;
|
|
28
|
-
data?: TData;
|
|
29
|
-
};
|
|
30
|
-
type CheckPartnerIdResult = {
|
|
31
|
-
success: boolean;
|
|
32
|
-
partnerId?: string;
|
|
33
|
-
message?: string;
|
|
34
|
-
status?: number;
|
|
35
|
-
};
|
|
36
|
-
type AssignPartnerIdInput = {
|
|
37
|
-
shopDomain: string;
|
|
38
|
-
partnerId: string;
|
|
39
|
-
};
|
|
40
|
-
type SubscriptionEventData = {
|
|
41
|
-
subscriptionStatus?: string;
|
|
42
|
-
subscriptionName?: string;
|
|
43
|
-
subscriptionId?: number | string;
|
|
44
|
-
subscriptionPrice?: number | string;
|
|
45
|
-
subscriptionPeriod?: string;
|
|
46
|
-
};
|
|
47
|
-
type AppsCatalogEntry = {
|
|
48
|
-
key: string;
|
|
49
|
-
type: string;
|
|
50
|
-
title: string;
|
|
51
|
-
company?: string;
|
|
52
|
-
companyUrl?: string;
|
|
53
|
-
desc?: string;
|
|
54
|
-
url: string;
|
|
55
|
-
icon?: string;
|
|
56
|
-
enabled?: boolean;
|
|
57
|
-
priority?: number;
|
|
58
|
-
locales?: string[];
|
|
59
|
-
};
|
|
60
|
-
type CrossSellOptions = {
|
|
61
|
-
appName?: string;
|
|
62
|
-
installedAppKeys?: string[];
|
|
63
|
-
locale?: string;
|
|
64
|
-
shopPlan?: string;
|
|
65
|
-
appsCatalog?: AppsCatalogEntry[];
|
|
66
|
-
};
|
|
67
|
-
type CrossSellFetchOptions = CrossSellOptions & {
|
|
68
|
-
appsCatalogUrl?: string;
|
|
69
|
-
limit?: number;
|
|
70
|
-
fetch?: FetchLike;
|
|
71
|
-
logger?: Logger;
|
|
72
|
-
};
|
|
1
|
+
import { C as ConnectorConfig, T as TrackEventParams, a as TrackResult, S as SubscriptionEventData, A as AssignPartnerIdInput, b as CheckPartnerIdResult } from './crossSell-BFz9e72n.js';
|
|
2
|
+
export { d as AppsCatalogEntry, e as CrossSellFetchOptions, h as CrossSellOptions, L as Logger, i as TrackEventName, f as fetchAppsCatalog, g as getCrossSellOffers, c as getCrossSellOffersFromApi } from './crossSell-BFz9e72n.js';
|
|
73
3
|
|
|
74
4
|
type Connector = {
|
|
75
5
|
track: (eventName: TrackEventParams["eventName"], payload: Omit<TrackEventParams, "eventName">) => Promise<TrackResult>;
|
|
@@ -101,12 +31,8 @@ type Connector = {
|
|
|
101
31
|
};
|
|
102
32
|
declare function createProgusConnector(config: ConnectorConfig): Connector;
|
|
103
33
|
|
|
104
|
-
declare function getCrossSellOffers(options?: CrossSellOptions): AppsCatalogEntry[];
|
|
105
|
-
declare function fetchAppsCatalog(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
106
|
-
declare function getCrossSellOffersFromApi(options?: CrossSellFetchOptions): Promise<AppsCatalogEntry[]>;
|
|
107
|
-
|
|
108
34
|
declare function signPayload(body: string, secret: string): string;
|
|
109
35
|
|
|
110
36
|
declare function normalizePartnerId(value?: string | null): string | null;
|
|
111
37
|
|
|
112
|
-
export {
|
|
38
|
+
export { AssignPartnerIdInput, CheckPartnerIdResult, ConnectorConfig, SubscriptionEventData, TrackEventParams, TrackResult, createProgusConnector, normalizePartnerId, signPayload };
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildEventId,
|
|
3
|
+
fetchAppsCatalog,
|
|
4
|
+
getCrossSellOffers,
|
|
5
|
+
getCrossSellOffersFromApi,
|
|
6
|
+
normalizePartnerId,
|
|
7
|
+
safeJsonParse,
|
|
8
|
+
stripTrailingSlash
|
|
9
|
+
} from "./chunk-WZ5FAA44.js";
|
|
10
|
+
|
|
1
11
|
// src/signing.ts
|
|
2
12
|
import { createHmac } from "crypto";
|
|
3
13
|
function signPayload(body, secret) {
|
|
4
14
|
return createHmac("sha256", secret).update(body).digest("hex");
|
|
5
15
|
}
|
|
6
16
|
|
|
7
|
-
// src/utils.ts
|
|
8
|
-
function normalizePartnerId(value) {
|
|
9
|
-
if (!value) return null;
|
|
10
|
-
const trimmed = value.trim();
|
|
11
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
12
|
-
}
|
|
13
|
-
function buildEventId(shopDomain, eventName, externalId) {
|
|
14
|
-
if (!externalId) return void 0;
|
|
15
|
-
return `${shopDomain}:${eventName}:${externalId}`;
|
|
16
|
-
}
|
|
17
|
-
function stripTrailingSlash(value) {
|
|
18
|
-
return value.replace(/\/+$/, "");
|
|
19
|
-
}
|
|
20
|
-
function safeJsonParse(text) {
|
|
21
|
-
try {
|
|
22
|
-
return JSON.parse(text);
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
17
|
// src/connector.ts
|
|
29
18
|
function createProgusConnector(config) {
|
|
30
19
|
const apiBaseUrl = config.apiBaseUrl ? stripTrailingSlash(config.apiBaseUrl) : "";
|
|
@@ -218,105 +207,6 @@ function createProgusConnector(config) {
|
|
|
218
207
|
checkPartnerId
|
|
219
208
|
};
|
|
220
209
|
}
|
|
221
|
-
|
|
222
|
-
// src/crossSell.ts
|
|
223
|
-
function getCrossSellOffers(options = {}) {
|
|
224
|
-
const appsCatalog = options.appsCatalog ?? [];
|
|
225
|
-
const installedKeys = new Set(
|
|
226
|
-
[options.appName, ...options.installedAppKeys ?? []].filter(
|
|
227
|
-
(key) => Boolean(key)
|
|
228
|
-
)
|
|
229
|
-
);
|
|
230
|
-
const locale = options.locale;
|
|
231
|
-
return appsCatalog.filter((app) => app.enabled !== false).filter((app) => locale ? !app.locales || app.locales.includes(locale) : true).filter((app) => !installedKeys.has(app.key)).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
232
|
-
}
|
|
233
|
-
var DEFAULT_APPS_CATALOG_URL = "https://appsdata.progus.com/recommendations";
|
|
234
|
-
var FALLBACK_APPS_CATALOG = [
|
|
235
|
-
{
|
|
236
|
-
key: "progus_ai_studio",
|
|
237
|
-
type: "app",
|
|
238
|
-
title: "Progus AI Studio",
|
|
239
|
-
company: "Progus",
|
|
240
|
-
companyUrl: "https://progus.com",
|
|
241
|
-
desc: "Generate on-brand AI product & variant images in bulk.",
|
|
242
|
-
url: "https://apps.shopify.com/progus-ai-studio",
|
|
243
|
-
icon: "https://cdn.shopify.com/app-store/listing_images/9428a41ed53c66cd7329a2583cd2f3d9/icon/COje1rnS4pEDEAE=.png",
|
|
244
|
-
priority: 100,
|
|
245
|
-
enabled: true
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
key: "progus_trust_badges",
|
|
249
|
-
type: "app",
|
|
250
|
-
title: "Progus Trust Badges",
|
|
251
|
-
company: "Progus",
|
|
252
|
-
companyUrl: "https://progus.com",
|
|
253
|
-
desc: "Add Trust Badges to your store to build trust and credibility.",
|
|
254
|
-
url: "https://apps.shopify.com/progus-trust-badges-1",
|
|
255
|
-
icon: "https://cdn.shopify.com/app-store/listing_images/f9d0009e237f27d2db35b41ef99be858/icon/CJ3y1qDn1JEDEAE=.png",
|
|
256
|
-
priority: 80,
|
|
257
|
-
enabled: true
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
key: "progus_cod",
|
|
261
|
-
type: "app",
|
|
262
|
-
title: "Progus COD",
|
|
263
|
-
company: "Progus",
|
|
264
|
-
companyUrl: "https://progus.com",
|
|
265
|
-
desc: "Automate COD Fees & Hide/Show Cash on Delivery by Rules.",
|
|
266
|
-
url: "https://apps.shopify.com/progus-cod",
|
|
267
|
-
icon: "https://cdn.shopify.com/app-store/listing_images/bc537219cc3ed2bd4e7e3e683fe6b74a/icon/CMi_6dTEkIoDEAE=.png",
|
|
268
|
-
priority: 90,
|
|
269
|
-
enabled: true
|
|
270
|
-
}
|
|
271
|
-
];
|
|
272
|
-
function buildFallbackCatalog(options) {
|
|
273
|
-
const appName = options.appName;
|
|
274
|
-
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
275
|
-
let items = FALLBACK_APPS_CATALOG.filter((app) => app.enabled !== false);
|
|
276
|
-
if (appName) {
|
|
277
|
-
items = items.filter((app) => app.key !== appName);
|
|
278
|
-
}
|
|
279
|
-
if (limit > 0) {
|
|
280
|
-
items = items.slice(0, limit);
|
|
281
|
-
}
|
|
282
|
-
return items;
|
|
283
|
-
}
|
|
284
|
-
async function fetchAppsCatalog(options = {}) {
|
|
285
|
-
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
286
|
-
const logger = options.logger ?? console;
|
|
287
|
-
const appName = options.appName;
|
|
288
|
-
const baseUrl = stripTrailingSlash(options.appsCatalogUrl ?? DEFAULT_APPS_CATALOG_URL);
|
|
289
|
-
const limit = typeof options.limit === "number" ? options.limit : 3;
|
|
290
|
-
const params = new URLSearchParams();
|
|
291
|
-
if (appName) params.set("appName", appName);
|
|
292
|
-
if (limit > 0) params.set("limit", String(limit));
|
|
293
|
-
const url = params.toString() ? `${baseUrl}?${params.toString()}` : baseUrl;
|
|
294
|
-
if (!fetchImpl) {
|
|
295
|
-
logger?.error?.("Failed to fetch apps catalog", {
|
|
296
|
-
error: "Fetch implementation is required"
|
|
297
|
-
});
|
|
298
|
-
return buildFallbackCatalog(options);
|
|
299
|
-
}
|
|
300
|
-
try {
|
|
301
|
-
const response = await fetchImpl(url);
|
|
302
|
-
const text = await response.text();
|
|
303
|
-
const parsed = safeJsonParse(text);
|
|
304
|
-
if (!response.ok || !parsed) {
|
|
305
|
-
logger?.error?.("Failed to fetch apps catalog", { status: response.status });
|
|
306
|
-
return buildFallbackCatalog(options);
|
|
307
|
-
}
|
|
308
|
-
return parsed;
|
|
309
|
-
} catch (error) {
|
|
310
|
-
logger?.error?.("Failed to fetch apps catalog", {
|
|
311
|
-
error: error instanceof Error ? error.message : String(error)
|
|
312
|
-
});
|
|
313
|
-
return buildFallbackCatalog(options);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
async function getCrossSellOffersFromApi(options = {}) {
|
|
317
|
-
const appsCatalog = options.appsCatalog ?? await fetchAppsCatalog(options);
|
|
318
|
-
return getCrossSellOffers({ ...options, appsCatalog });
|
|
319
|
-
}
|
|
320
210
|
export {
|
|
321
211
|
createProgusConnector,
|
|
322
212
|
fetchAppsCatalog,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@progus/connector",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Progus partner/affiliate connector helpers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
13
|
"import": "./dist/index.js",
|
|
14
14
|
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./crossSell": {
|
|
17
|
+
"types": "./dist/crossSell.d.ts",
|
|
18
|
+
"import": "./dist/crossSell.js",
|
|
19
|
+
"require": "./dist/crossSell.cjs"
|
|
15
20
|
}
|
|
16
21
|
},
|
|
17
22
|
"files": [
|
|
@@ -26,8 +31,8 @@
|
|
|
26
31
|
"access": "public"
|
|
27
32
|
},
|
|
28
33
|
"scripts": {
|
|
29
|
-
"build": "tsup src/index.ts --format esm,cjs --dts --clean --target node18",
|
|
30
|
-
"dev": "tsup src/index.ts --format esm,cjs --dts --watch --target node18",
|
|
34
|
+
"build": "tsup src/index.ts src/crossSell.ts --format esm,cjs --dts --clean --target node18",
|
|
35
|
+
"dev": "tsup src/index.ts src/crossSell.ts --format esm,cjs --dts --watch --target node18",
|
|
31
36
|
"smoke": "tsx scripts/smoke.ts"
|
|
32
37
|
},
|
|
33
38
|
"devDependencies": {
|