@behio/storefront-sdk 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Y7QAB75P.mjs → chunk-5KJDVDUM.mjs} +43 -0
- package/dist/chunk-CZRSJULD.js +118 -0
- package/dist/chunk-QUU76QUB.mjs +118 -0
- package/dist/{chunk-5OFVG2BO.js → chunk-Y4ZCK5HD.js} +43 -0
- package/dist/{client-BOz1trRk.d.mts → client-DdaC0_6x.d.mts} +239 -5
- package/dist/{client-BOz1trRk.d.ts → client-DdaC0_6x.d.ts} +239 -5
- package/dist/index.d.mts +86 -8
- package/dist/index.d.ts +86 -8
- package/dist/index.js +11 -3
- package/dist/index.mjs +10 -2
- package/dist/next.d.mts +1 -1
- package/dist/next.d.ts +1 -1
- package/dist/next.js +2 -2
- package/dist/next.mjs +1 -1
- package/dist/react.d.mts +172 -4
- package/dist/react.d.ts +172 -4
- package/dist/react.js +285 -55
- package/dist/react.mjs +325 -95
- package/package.json +1 -1
- package/dist/chunk-JIAOZ5YW.js +0 -40
- package/dist/chunk-ZOZAJG6T.mjs +0 -40
|
@@ -147,6 +147,7 @@ var BehioStorefront = class {
|
|
|
147
147
|
this.addresses = new AddressModule(this);
|
|
148
148
|
this.shipping = new ShippingModule(this);
|
|
149
149
|
this.newsletter = new NewsletterModule(this);
|
|
150
|
+
this.subscriptions = new SubscriptionsModule(this);
|
|
150
151
|
}
|
|
151
152
|
// --- Public methods ---
|
|
152
153
|
/**
|
|
@@ -1033,6 +1034,40 @@ var WishlistModule = class {
|
|
|
1033
1034
|
return this.client.request("GET", `/customer/wishlist/${productId}/check`);
|
|
1034
1035
|
}
|
|
1035
1036
|
};
|
|
1037
|
+
var SubscriptionsModule = class {
|
|
1038
|
+
constructor(client) {
|
|
1039
|
+
this.client = client;
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* List the logged-in customer's recurring-order subscriptions (products,
|
|
1043
|
+
* cadence, next order date, status). Requires an authenticated customer
|
|
1044
|
+
* session. Subscriptions are created by the merchant in v1.
|
|
1045
|
+
*/
|
|
1046
|
+
async list() {
|
|
1047
|
+
return this.client.request("GET", "/customer/subscriptions");
|
|
1048
|
+
}
|
|
1049
|
+
/** Pause an active subscription (no orders are generated while paused). */
|
|
1050
|
+
async pause(subscriptionId) {
|
|
1051
|
+
return this.client.request(
|
|
1052
|
+
"POST",
|
|
1053
|
+
`/customer/subscriptions/${subscriptionId}/pause`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
/** Resume a paused subscription (re-schedules the next order). */
|
|
1057
|
+
async resume(subscriptionId) {
|
|
1058
|
+
return this.client.request(
|
|
1059
|
+
"POST",
|
|
1060
|
+
`/customer/subscriptions/${subscriptionId}/resume`
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
/** Cancel a subscription permanently (no more orders). */
|
|
1064
|
+
async cancel(subscriptionId) {
|
|
1065
|
+
return this.client.request(
|
|
1066
|
+
"POST",
|
|
1067
|
+
`/customer/subscriptions/${subscriptionId}/cancel`
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1036
1071
|
var ReviewsModule = class {
|
|
1037
1072
|
constructor(client) {
|
|
1038
1073
|
this.client = client;
|
|
@@ -1104,6 +1139,14 @@ var QuotesModule = class {
|
|
|
1104
1139
|
async getStatus(quoteId, email) {
|
|
1105
1140
|
return this.client.request("POST", `/quotes/${quoteId}/status`, { body: { email } });
|
|
1106
1141
|
}
|
|
1142
|
+
/**
|
|
1143
|
+
* The logged-in customer's own quote requests ("Moje poptávky", GAP-18).
|
|
1144
|
+
* Requires an authenticated session; ownership is the auth token (customer id
|
|
1145
|
+
* + verified email), never a payload. Newest first.
|
|
1146
|
+
*/
|
|
1147
|
+
async listMine() {
|
|
1148
|
+
return this.client.request("GET", "/customer/quotes");
|
|
1149
|
+
}
|
|
1107
1150
|
};
|
|
1108
1151
|
var AddressModule = class {
|
|
1109
1152
|
constructor(client) {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/react/utils/format-price.ts
|
|
2
|
+
function formatPrice(amount, currency, locale) {
|
|
3
|
+
const resolvedLocale = _nullishCoalesce(locale, () => ( "cs"));
|
|
4
|
+
try {
|
|
5
|
+
return new Intl.NumberFormat(resolvedLocale, {
|
|
6
|
+
style: "currency",
|
|
7
|
+
currency,
|
|
8
|
+
minimumFractionDigits: Number.isInteger(amount) ? 0 : 2,
|
|
9
|
+
maximumFractionDigits: 2
|
|
10
|
+
}).format(amount);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return `${amount} ${currency}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/analytics.ts
|
|
17
|
+
var GA4_NAME_MAP = {
|
|
18
|
+
newsletter_signup: "generate_lead"
|
|
19
|
+
};
|
|
20
|
+
function trackEcommerceEvent(event, payload) {
|
|
21
|
+
if (typeof window === "undefined") return;
|
|
22
|
+
const w = window;
|
|
23
|
+
try {
|
|
24
|
+
_optionalChain([w, 'access', _ => _.__behioEcommerceSink, 'optionalCall', _2 => _2(event, payload)]);
|
|
25
|
+
} catch (e2) {
|
|
26
|
+
}
|
|
27
|
+
const gaName = _nullishCoalesce(GA4_NAME_MAP[event], () => ( event));
|
|
28
|
+
try {
|
|
29
|
+
if (typeof w.gtag === "function") {
|
|
30
|
+
w.gtag("event", gaName, payload);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(w.dataLayer)) {
|
|
34
|
+
w.dataLayer.push({ ecommerce: null });
|
|
35
|
+
w.dataLayer.push({ event: gaName, ecommerce: payload });
|
|
36
|
+
}
|
|
37
|
+
} catch (e3) {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/consent-visitor.ts
|
|
42
|
+
var VISITOR_KEY = "behio_visitor_id";
|
|
43
|
+
var COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
|
|
44
|
+
function getStoredVisitorId() {
|
|
45
|
+
if (typeof window === "undefined") return null;
|
|
46
|
+
try {
|
|
47
|
+
const ls = localStorage.getItem(VISITOR_KEY);
|
|
48
|
+
if (ls) return ls;
|
|
49
|
+
} catch (e4) {
|
|
50
|
+
}
|
|
51
|
+
return readCookie(VISITOR_KEY);
|
|
52
|
+
}
|
|
53
|
+
function generateVisitorId() {
|
|
54
|
+
const bytes = new Uint8Array(18);
|
|
55
|
+
try {
|
|
56
|
+
_optionalChain([globalThis, 'access', _3 => _3.crypto, 'optionalAccess', _4 => _4.getRandomValues, 'optionalCall', _5 => _5(bytes)]);
|
|
57
|
+
} catch (e5) {
|
|
58
|
+
}
|
|
59
|
+
let filled = false;
|
|
60
|
+
for (const b of bytes) if (b !== 0) filled = true;
|
|
61
|
+
if (!filled) for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
62
|
+
let bin = "";
|
|
63
|
+
for (const b of bytes) bin += String.fromCharCode(b);
|
|
64
|
+
const b64 = typeof btoa === "function" ? btoa(bin) : Buffer.from(bytes).toString("base64");
|
|
65
|
+
return `v${b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")}`.slice(0, 40);
|
|
66
|
+
}
|
|
67
|
+
function writeVisitorId(id) {
|
|
68
|
+
if (typeof window === "undefined") return;
|
|
69
|
+
try {
|
|
70
|
+
localStorage.setItem(VISITOR_KEY, id);
|
|
71
|
+
} catch (e6) {
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
document.cookie = `${VISITOR_KEY}=${encodeURIComponent(id)}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax`;
|
|
75
|
+
} catch (e7) {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function readCookie(name) {
|
|
79
|
+
if (typeof document === "undefined") return null;
|
|
80
|
+
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
81
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
82
|
+
}
|
|
83
|
+
function emitConsentChanged() {
|
|
84
|
+
if (typeof window === "undefined") return;
|
|
85
|
+
try {
|
|
86
|
+
window.dispatchEvent(new Event("behio:consent-changed"));
|
|
87
|
+
} catch (e8) {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function grantAnalyticsConsent(client, categories) {
|
|
91
|
+
const id = _nullishCoalesce(getStoredVisitorId(), () => ( generateVisitorId()));
|
|
92
|
+
writeVisitorId(id);
|
|
93
|
+
client.setAnalyticsVisitorId(id);
|
|
94
|
+
const res = await client.consent.record({
|
|
95
|
+
visitorId: id,
|
|
96
|
+
analytics: true,
|
|
97
|
+
marketing: _nullishCoalesce(_optionalChain([categories, 'optionalAccess', _6 => _6.marketing]), () => ( false)),
|
|
98
|
+
preferences: _nullishCoalesce(_optionalChain([categories, 'optionalAccess', _7 => _7.preferences]), () => ( false))
|
|
99
|
+
});
|
|
100
|
+
emitConsentChanged();
|
|
101
|
+
return res;
|
|
102
|
+
}
|
|
103
|
+
async function revokeAnalyticsConsent(client) {
|
|
104
|
+
const id = getStoredVisitorId();
|
|
105
|
+
client.setAnalyticsVisitorId(null);
|
|
106
|
+
emitConsentChanged();
|
|
107
|
+
if (!id) return { data: { success: true }, error: null };
|
|
108
|
+
return client.consent.revoke(id);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
exports.formatPrice = formatPrice; exports.trackEcommerceEvent = trackEcommerceEvent; exports.getStoredVisitorId = getStoredVisitorId; exports.generateVisitorId = generateVisitorId; exports.grantAnalyticsConsent = grantAnalyticsConsent; exports.revokeAnalyticsConsent = revokeAnalyticsConsent;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// src/react/utils/format-price.ts
|
|
2
|
+
function formatPrice(amount, currency, locale) {
|
|
3
|
+
const resolvedLocale = locale ?? "cs";
|
|
4
|
+
try {
|
|
5
|
+
return new Intl.NumberFormat(resolvedLocale, {
|
|
6
|
+
style: "currency",
|
|
7
|
+
currency,
|
|
8
|
+
minimumFractionDigits: Number.isInteger(amount) ? 0 : 2,
|
|
9
|
+
maximumFractionDigits: 2
|
|
10
|
+
}).format(amount);
|
|
11
|
+
} catch {
|
|
12
|
+
return `${amount} ${currency}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// src/analytics.ts
|
|
17
|
+
var GA4_NAME_MAP = {
|
|
18
|
+
newsletter_signup: "generate_lead"
|
|
19
|
+
};
|
|
20
|
+
function trackEcommerceEvent(event, payload) {
|
|
21
|
+
if (typeof window === "undefined") return;
|
|
22
|
+
const w = window;
|
|
23
|
+
try {
|
|
24
|
+
w.__behioEcommerceSink?.(event, payload);
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
const gaName = GA4_NAME_MAP[event] ?? event;
|
|
28
|
+
try {
|
|
29
|
+
if (typeof w.gtag === "function") {
|
|
30
|
+
w.gtag("event", gaName, payload);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (Array.isArray(w.dataLayer)) {
|
|
34
|
+
w.dataLayer.push({ ecommerce: null });
|
|
35
|
+
w.dataLayer.push({ event: gaName, ecommerce: payload });
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/consent-visitor.ts
|
|
42
|
+
var VISITOR_KEY = "behio_visitor_id";
|
|
43
|
+
var COOKIE_MAX_AGE = 60 * 60 * 24 * 365;
|
|
44
|
+
function getStoredVisitorId() {
|
|
45
|
+
if (typeof window === "undefined") return null;
|
|
46
|
+
try {
|
|
47
|
+
const ls = localStorage.getItem(VISITOR_KEY);
|
|
48
|
+
if (ls) return ls;
|
|
49
|
+
} catch {
|
|
50
|
+
}
|
|
51
|
+
return readCookie(VISITOR_KEY);
|
|
52
|
+
}
|
|
53
|
+
function generateVisitorId() {
|
|
54
|
+
const bytes = new Uint8Array(18);
|
|
55
|
+
try {
|
|
56
|
+
globalThis.crypto?.getRandomValues?.(bytes);
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
let filled = false;
|
|
60
|
+
for (const b of bytes) if (b !== 0) filled = true;
|
|
61
|
+
if (!filled) for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);
|
|
62
|
+
let bin = "";
|
|
63
|
+
for (const b of bytes) bin += String.fromCharCode(b);
|
|
64
|
+
const b64 = typeof btoa === "function" ? btoa(bin) : Buffer.from(bytes).toString("base64");
|
|
65
|
+
return `v${b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")}`.slice(0, 40);
|
|
66
|
+
}
|
|
67
|
+
function writeVisitorId(id) {
|
|
68
|
+
if (typeof window === "undefined") return;
|
|
69
|
+
try {
|
|
70
|
+
localStorage.setItem(VISITOR_KEY, id);
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
document.cookie = `${VISITOR_KEY}=${encodeURIComponent(id)}; path=/; max-age=${COOKIE_MAX_AGE}; SameSite=Lax`;
|
|
75
|
+
} catch {
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function readCookie(name) {
|
|
79
|
+
if (typeof document === "undefined") return null;
|
|
80
|
+
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
81
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
82
|
+
}
|
|
83
|
+
function emitConsentChanged() {
|
|
84
|
+
if (typeof window === "undefined") return;
|
|
85
|
+
try {
|
|
86
|
+
window.dispatchEvent(new Event("behio:consent-changed"));
|
|
87
|
+
} catch {
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async function grantAnalyticsConsent(client, categories) {
|
|
91
|
+
const id = getStoredVisitorId() ?? generateVisitorId();
|
|
92
|
+
writeVisitorId(id);
|
|
93
|
+
client.setAnalyticsVisitorId(id);
|
|
94
|
+
const res = await client.consent.record({
|
|
95
|
+
visitorId: id,
|
|
96
|
+
analytics: true,
|
|
97
|
+
marketing: categories?.marketing ?? false,
|
|
98
|
+
preferences: categories?.preferences ?? false
|
|
99
|
+
});
|
|
100
|
+
emitConsentChanged();
|
|
101
|
+
return res;
|
|
102
|
+
}
|
|
103
|
+
async function revokeAnalyticsConsent(client) {
|
|
104
|
+
const id = getStoredVisitorId();
|
|
105
|
+
client.setAnalyticsVisitorId(null);
|
|
106
|
+
emitConsentChanged();
|
|
107
|
+
if (!id) return { data: { success: true }, error: null };
|
|
108
|
+
return client.consent.revoke(id);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
formatPrice,
|
|
113
|
+
trackEcommerceEvent,
|
|
114
|
+
getStoredVisitorId,
|
|
115
|
+
generateVisitorId,
|
|
116
|
+
grantAnalyticsConsent,
|
|
117
|
+
revokeAnalyticsConsent
|
|
118
|
+
};
|
|
@@ -147,6 +147,7 @@ var BehioStorefront = class {
|
|
|
147
147
|
this.addresses = new AddressModule(this);
|
|
148
148
|
this.shipping = new ShippingModule(this);
|
|
149
149
|
this.newsletter = new NewsletterModule(this);
|
|
150
|
+
this.subscriptions = new SubscriptionsModule(this);
|
|
150
151
|
}
|
|
151
152
|
// --- Public methods ---
|
|
152
153
|
/**
|
|
@@ -1033,6 +1034,40 @@ var WishlistModule = class {
|
|
|
1033
1034
|
return this.client.request("GET", `/customer/wishlist/${productId}/check`);
|
|
1034
1035
|
}
|
|
1035
1036
|
};
|
|
1037
|
+
var SubscriptionsModule = class {
|
|
1038
|
+
constructor(client) {
|
|
1039
|
+
this.client = client;
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* List the logged-in customer's recurring-order subscriptions (products,
|
|
1043
|
+
* cadence, next order date, status). Requires an authenticated customer
|
|
1044
|
+
* session. Subscriptions are created by the merchant in v1.
|
|
1045
|
+
*/
|
|
1046
|
+
async list() {
|
|
1047
|
+
return this.client.request("GET", "/customer/subscriptions");
|
|
1048
|
+
}
|
|
1049
|
+
/** Pause an active subscription (no orders are generated while paused). */
|
|
1050
|
+
async pause(subscriptionId) {
|
|
1051
|
+
return this.client.request(
|
|
1052
|
+
"POST",
|
|
1053
|
+
`/customer/subscriptions/${subscriptionId}/pause`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
/** Resume a paused subscription (re-schedules the next order). */
|
|
1057
|
+
async resume(subscriptionId) {
|
|
1058
|
+
return this.client.request(
|
|
1059
|
+
"POST",
|
|
1060
|
+
`/customer/subscriptions/${subscriptionId}/resume`
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
/** Cancel a subscription permanently (no more orders). */
|
|
1064
|
+
async cancel(subscriptionId) {
|
|
1065
|
+
return this.client.request(
|
|
1066
|
+
"POST",
|
|
1067
|
+
`/customer/subscriptions/${subscriptionId}/cancel`
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1036
1071
|
var ReviewsModule = class {
|
|
1037
1072
|
constructor(client) {
|
|
1038
1073
|
this.client = client;
|
|
@@ -1104,6 +1139,14 @@ var QuotesModule = class {
|
|
|
1104
1139
|
async getStatus(quoteId, email) {
|
|
1105
1140
|
return this.client.request("POST", `/quotes/${quoteId}/status`, { body: { email } });
|
|
1106
1141
|
}
|
|
1142
|
+
/**
|
|
1143
|
+
* The logged-in customer's own quote requests ("Moje poptávky", GAP-18).
|
|
1144
|
+
* Requires an authenticated session; ownership is the auth token (customer id
|
|
1145
|
+
* + verified email), never a payload. Newest first.
|
|
1146
|
+
*/
|
|
1147
|
+
async listMine() {
|
|
1148
|
+
return this.client.request("GET", "/customer/quotes");
|
|
1149
|
+
}
|
|
1107
1150
|
};
|
|
1108
1151
|
var AddressModule = class {
|
|
1109
1152
|
constructor(client) {
|