@tagadapay/headless-sdk 1.14.1 → 1.17.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/core/client.d.ts +12 -0
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +16 -4
- package/dist/core/client.js.map +1 -1
- package/dist/core/http.d.ts +2 -0
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +21 -5
- package/dist/core/http.js.map +1 -1
- package/dist/core/index.d.ts +7 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/modules/checkout.d.ts +5 -1
- package/dist/core/modules/checkout.d.ts.map +1 -1
- package/dist/core/modules/checkout.js +22 -1
- package/dist/core/modules/checkout.js.map +1 -1
- package/dist/core/modules/commerce.d.ts +4 -0
- package/dist/core/modules/commerce.d.ts.map +1 -0
- package/dist/core/modules/commerce.js +5 -0
- package/dist/core/modules/commerce.js.map +1 -0
- package/dist/core/modules/customer.d.ts +47 -1
- package/dist/core/modules/customer.d.ts.map +1 -1
- package/dist/core/modules/customer.js +60 -3
- package/dist/core/modules/customer.js.map +1 -1
- package/dist/core/modules/experiments.d.ts +21 -0
- package/dist/core/modules/experiments.d.ts.map +1 -0
- package/dist/core/modules/experiments.js +85 -0
- package/dist/core/modules/experiments.js.map +1 -0
- package/dist/core/modules/funnel.d.ts +2 -1
- package/dist/core/modules/funnel.d.ts.map +1 -1
- package/dist/core/modules/funnel.js +6 -1
- package/dist/core/modules/funnel.js.map +1 -1
- package/dist/core/modules/lazyCommerce.d.ts +16 -0
- package/dist/core/modules/lazyCommerce.d.ts.map +1 -0
- package/dist/core/modules/lazyCommerce.js +20 -0
- package/dist/core/modules/lazyCommerce.js.map +1 -0
- package/dist/core/modules/offers.d.ts +30 -5
- package/dist/core/modules/offers.d.ts.map +1 -1
- package/dist/core/modules/offers.js +66 -7
- package/dist/core/modules/offers.js.map +1 -1
- package/dist/core/modules/payment.d.ts +19 -1
- package/dist/core/modules/payment.d.ts.map +1 -1
- package/dist/core/modules/payment.js +42 -3
- package/dist/core/modules/payment.js.map +1 -1
- package/dist/core/modules/portal/index.d.ts +102 -0
- package/dist/core/modules/portal/index.d.ts.map +1 -0
- package/dist/core/modules/portal/index.js +166 -0
- package/dist/core/modules/portal/index.js.map +1 -0
- package/dist/core/modules/portal/types.d.ts +617 -0
- package/dist/core/modules/portal/types.d.ts.map +1 -0
- package/dist/core/modules/portal/types.js +11 -0
- package/dist/core/modules/portal/types.js.map +1 -0
- package/dist/core/modules/rx.d.ts +32 -1
- package/dist/core/modules/rx.d.ts.map +1 -1
- package/dist/core/modules/rx.js +17 -1
- package/dist/core/modules/rx.js.map +1 -1
- package/dist/core/modules/track.d.ts +135 -0
- package/dist/core/modules/track.d.ts.map +1 -0
- package/dist/core/modules/track.js +412 -0
- package/dist/core/modules/track.js.map +1 -0
- package/dist/core/types.d.ts +13 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +0 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/version.d.ts +4 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +4 -0
- package/dist/core/version.js.map +1 -0
- package/dist/pixels/engine.d.ts +56 -0
- package/dist/pixels/engine.d.ts.map +1 -0
- package/dist/pixels/engine.js +263 -0
- package/dist/pixels/engine.js.map +1 -0
- package/dist/pixels/index.d.ts +10 -0
- package/dist/pixels/index.d.ts.map +1 -0
- package/dist/pixels/index.js +5 -0
- package/dist/pixels/index.js.map +1 -0
- package/dist/pixels/metaEventId.d.ts +15 -0
- package/dist/pixels/metaEventId.d.ts.map +1 -0
- package/dist/pixels/metaEventId.js +17 -0
- package/dist/pixels/metaEventId.js.map +1 -0
- package/dist/pixels/pixelIdentity.d.ts +34 -0
- package/dist/pixels/pixelIdentity.d.ts.map +1 -0
- package/dist/pixels/pixelIdentity.js +65 -0
- package/dist/pixels/pixelIdentity.js.map +1 -0
- package/dist/pixels/pixelMapping.d.ts +172 -0
- package/dist/pixels/pixelMapping.d.ts.map +1 -0
- package/dist/pixels/pixelMapping.js +574 -0
- package/dist/pixels/pixelMapping.js.map +1 -0
- package/dist/pixels/pixelTracker.d.ts +81 -0
- package/dist/pixels/pixelTracker.d.ts.map +1 -0
- package/dist/pixels/pixelTracker.js +797 -0
- package/dist/pixels/pixelTracker.js.map +1 -0
- package/dist/pixels/types.d.ts +103 -0
- package/dist/pixels/types.d.ts.map +1 -0
- package/dist/pixels/types.js +14 -0
- package/dist/pixels/types.js.map +1 -0
- package/dist/react/hooks/useStep.d.ts +7 -0
- package/dist/react/hooks/useStep.d.ts.map +1 -0
- package/dist/react/hooks/useStep.js +14 -0
- package/dist/react/hooks/useStep.js.map +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/stripe/index.d.ts +3 -1
- package/dist/stripe/index.d.ts.map +1 -1
- package/dist/stripe/index.js +13 -6
- package/dist/stripe/index.js.map +1 -1
- package/dist/stripe/useStripeExpress.d.ts.map +1 -1
- package/dist/stripe/useStripeExpress.js +15 -1
- package/dist/stripe/useStripeExpress.js.map +1 -1
- package/dist/tagada-headless-commerce.min.js +8 -0
- package/dist/tagada-headless-commerce.min.js.map +7 -0
- package/dist/tagada-headless-react.min.js +2 -2
- package/dist/tagada-headless-react.min.js.map +4 -4
- package/dist/tagada-headless.js +722 -288
- package/dist/tagada-headless.min.js +2 -2
- package/dist/tagada-headless.min.js.map +4 -4
- package/dist/tagada-pixels.min.js +7 -0
- package/dist/tagada-pixels.min.js.map +7 -0
- package/dist/tgd/contract/attribution.d.ts +28 -0
- package/dist/tgd/contract/attribution.d.ts.map +1 -0
- package/dist/tgd/contract/attribution.js +44 -0
- package/dist/tgd/contract/attribution.js.map +1 -0
- package/dist/tgd/contract/browser-api.d.ts +57 -0
- package/dist/tgd/contract/browser-api.d.ts.map +1 -0
- package/dist/tgd/contract/browser-api.js +2 -0
- package/dist/tgd/contract/browser-api.js.map +1 -0
- package/dist/tgd/contract/canvas.d.ts +120 -0
- package/dist/tgd/contract/canvas.d.ts.map +1 -0
- package/dist/tgd/contract/canvas.js +12 -0
- package/dist/tgd/contract/canvas.js.map +1 -0
- package/dist/tgd/contract/dedup-keys.d.ts +24 -0
- package/dist/tgd/contract/dedup-keys.d.ts.map +1 -0
- package/dist/tgd/contract/dedup-keys.js +23 -0
- package/dist/tgd/contract/dedup-keys.js.map +1 -0
- package/dist/tgd/contract/destination-names.d.ts +4 -0
- package/dist/tgd/contract/destination-names.d.ts.map +1 -0
- package/dist/tgd/contract/destination-names.js +66 -0
- package/dist/tgd/contract/destination-names.js.map +1 -0
- package/dist/tgd/contract/destinations.d.ts +124 -0
- package/dist/tgd/contract/destinations.d.ts.map +1 -0
- package/dist/tgd/contract/destinations.js +63 -0
- package/dist/tgd/contract/destinations.js.map +1 -0
- package/dist/tgd/contract/envelope.d.ts +203 -0
- package/dist/tgd/contract/envelope.d.ts.map +1 -0
- package/dist/tgd/contract/envelope.js +103 -0
- package/dist/tgd/contract/envelope.js.map +1 -0
- package/dist/tgd/contract/experiments.d.ts +87 -0
- package/dist/tgd/contract/experiments.d.ts.map +1 -0
- package/dist/tgd/contract/experiments.js +2 -0
- package/dist/tgd/contract/experiments.js.map +1 -0
- package/dist/tgd/contract/index.d.ts +20 -0
- package/dist/tgd/contract/index.d.ts.map +1 -0
- package/dist/tgd/contract/index.js +20 -0
- package/dist/tgd/contract/index.js.map +1 -0
- package/dist/tgd/contract/is-test.d.ts +2 -0
- package/dist/tgd/contract/is-test.d.ts.map +1 -0
- package/dist/tgd/contract/is-test.js +3 -0
- package/dist/tgd/contract/is-test.js.map +1 -0
- package/dist/tgd/contract/junk-ids.d.ts +4 -0
- package/dist/tgd/contract/junk-ids.d.ts.map +1 -0
- package/dist/tgd/contract/junk-ids.js +7 -0
- package/dist/tgd/contract/junk-ids.js.map +1 -0
- package/dist/tgd/contract/limits.d.ts +19 -0
- package/dist/tgd/contract/limits.d.ts.map +1 -0
- package/dist/tgd/contract/limits.js +20 -0
- package/dist/tgd/contract/limits.js.map +1 -0
- package/dist/tgd/contract/names.d.ts +13 -0
- package/dist/tgd/contract/names.d.ts.map +1 -0
- package/dist/tgd/contract/names.js +15 -0
- package/dist/tgd/contract/names.js.map +1 -0
- package/dist/tgd/contract/registry.d.ts +116 -0
- package/dist/tgd/contract/registry.d.ts.map +1 -0
- package/dist/tgd/contract/registry.js +59 -0
- package/dist/tgd/contract/registry.js.map +1 -0
- package/dist/tgd/contract/signed-ids.d.ts +33 -0
- package/dist/tgd/contract/signed-ids.d.ts.map +1 -0
- package/dist/tgd/contract/signed-ids.js +26 -0
- package/dist/tgd/contract/signed-ids.js.map +1 -0
- package/dist/tgd/contract/snapshots.d.ts +69 -0
- package/dist/tgd/contract/snapshots.d.ts.map +1 -0
- package/dist/tgd/contract/snapshots.js +2 -0
- package/dist/tgd/contract/snapshots.js.map +1 -0
- package/dist/tgd/contract/time.d.ts +9 -0
- package/dist/tgd/contract/time.d.ts.map +1 -0
- package/dist/tgd/contract/time.js +9 -0
- package/dist/tgd/contract/time.js.map +1 -0
- package/dist/tgd/contract/unions.d.ts +21 -0
- package/dist/tgd/contract/unions.d.ts.map +1 -0
- package/dist/tgd/contract/unions.js +17 -0
- package/dist/tgd/contract/unions.js.map +1 -0
- package/dist/tgd/contract/unit.d.ts +12 -0
- package/dist/tgd/contract/unit.d.ts.map +1 -0
- package/dist/tgd/contract/unit.js +18 -0
- package/dist/tgd/contract/unit.js.map +1 -0
- package/dist/tgd/contract/wire.d.ts +59 -0
- package/dist/tgd/contract/wire.d.ts.map +1 -0
- package/dist/tgd/contract/wire.js +2 -0
- package/dist/tgd/contract/wire.js.map +1 -0
- package/package.json +8 -1
package/dist/tagada-headless.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @tagadapay/headless-sdk v1.
|
|
2
|
+
* @tagadapay/headless-sdk v1.17.0
|
|
3
3
|
* Headless checkout, payments, offers, and CRM
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
@@ -48,6 +48,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
48
48
|
CheckoutModule: () => CheckoutModule,
|
|
49
49
|
CurrencyUtils: () => CurrencyUtils,
|
|
50
50
|
CustomerModule: () => CustomerModule,
|
|
51
|
+
CustomerPortalModule: () => CustomerPortalModule,
|
|
52
|
+
ExperimentsModule: () => ExperimentsModule,
|
|
51
53
|
FunnelModule: () => FunnelModule,
|
|
52
54
|
GoogleAutocompleteCore: () => GoogleAutocompleteCore,
|
|
53
55
|
HeadlessClient: () => HeadlessClient,
|
|
@@ -63,6 +65,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
63
65
|
TagadaPaymentError: () => TagadaPaymentError,
|
|
64
66
|
TagadaRateLimitError: () => TagadaRateLimitError,
|
|
65
67
|
TagadaValidationError: () => TagadaValidationError,
|
|
68
|
+
TrackModule: () => TrackModule,
|
|
66
69
|
createHeadlessClient: () => createHeadlessClient,
|
|
67
70
|
ensureGeoDataLoaded: () => ensureGeoDataLoaded,
|
|
68
71
|
formatMoney: () => formatMoney,
|
|
@@ -137,6 +140,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
137
140
|
this.timeout = config.timeout;
|
|
138
141
|
this.apiKey = config.apiKey;
|
|
139
142
|
this.getToken = config.getToken;
|
|
143
|
+
this.redirect = config.redirect;
|
|
140
144
|
}
|
|
141
145
|
static resolveBaseUrl(environment, override) {
|
|
142
146
|
return override ?? BASE_URLS[environment] ?? BASE_URLS.production;
|
|
@@ -144,7 +148,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
144
148
|
async request(path, options = {}) {
|
|
145
149
|
var _a;
|
|
146
150
|
const { method = "GET", body, headers = {}, params, token, signal } = options;
|
|
147
|
-
let
|
|
151
|
+
let url2 = `${this.baseUrl}${path}`;
|
|
148
152
|
if (params) {
|
|
149
153
|
const qs = new URLSearchParams();
|
|
150
154
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -153,7 +157,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
153
157
|
}
|
|
154
158
|
const str = qs.toString();
|
|
155
159
|
if (str)
|
|
156
|
-
|
|
160
|
+
url2 += `?${str}`;
|
|
157
161
|
}
|
|
158
162
|
const reqHeaders = {
|
|
159
163
|
"Content-Type": "application/json",
|
|
@@ -166,11 +170,12 @@ var TagadaHeadlessBundle = (() => {
|
|
|
166
170
|
const controller = new AbortController();
|
|
167
171
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
168
172
|
try {
|
|
169
|
-
const res = await fetch(
|
|
173
|
+
const res = await fetch(url2, {
|
|
170
174
|
method,
|
|
171
175
|
headers: reqHeaders,
|
|
172
176
|
body: body != null ? JSON.stringify(body) : void 0,
|
|
173
|
-
signal: signal ?? controller.signal
|
|
177
|
+
signal: signal ?? controller.signal,
|
|
178
|
+
...this.redirect && { redirect: this.redirect }
|
|
174
179
|
});
|
|
175
180
|
clearTimeout(timeoutId);
|
|
176
181
|
if (res.ok) {
|
|
@@ -212,8 +217,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
212
217
|
parsed = await res.json();
|
|
213
218
|
} catch {
|
|
214
219
|
}
|
|
215
|
-
const data = parsed.data
|
|
216
|
-
const msg = parsed.message
|
|
220
|
+
const data = parseErrorData(parsed.data);
|
|
221
|
+
const msg = parsed.message || parsed.error || (typeof data.message === "string" ? data.message : void 0) || (typeof parsed.data === "string" && Object.keys(data).length === 0 ? parsed.data : void 0) || `Request failed: ${res.status} ${res.statusText} on ${path}`;
|
|
217
222
|
const appCode = typeof data.code === "string" ? data.code : void 0;
|
|
218
223
|
switch (res.status) {
|
|
219
224
|
case 401:
|
|
@@ -234,13 +239,26 @@ var TagadaHeadlessBundle = (() => {
|
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
241
|
};
|
|
242
|
+
function parseErrorData(value) {
|
|
243
|
+
if (value && typeof value === "object")
|
|
244
|
+
return value;
|
|
245
|
+
if (typeof value !== "string")
|
|
246
|
+
return {};
|
|
247
|
+
try {
|
|
248
|
+
const parsed = JSON.parse(value);
|
|
249
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
250
|
+
} catch {
|
|
251
|
+
return {};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
237
254
|
|
|
238
255
|
// src/core/modules/checkout.ts
|
|
239
256
|
var CheckoutModule = class _CheckoutModule {
|
|
240
|
-
constructor(http, storeId, onTokenChange) {
|
|
257
|
+
constructor(http, storeId, onTokenChange, onSession) {
|
|
241
258
|
this.http = http;
|
|
242
259
|
this.storeId = storeId;
|
|
243
260
|
this.onTokenChange = onTokenChange;
|
|
261
|
+
this.onSession = onSession;
|
|
244
262
|
}
|
|
245
263
|
/**
|
|
246
264
|
* Returns the most recently loaded `CheckoutSession`, if any.
|
|
@@ -264,7 +282,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
264
282
|
* Example URL: `/checkout?checkoutToken=abc123&token=eyJ...`
|
|
265
283
|
*/
|
|
266
284
|
async loadSession(checkoutToken, sessionToken, opts) {
|
|
267
|
-
var _a;
|
|
285
|
+
var _a, _b;
|
|
268
286
|
if (sessionToken) {
|
|
269
287
|
this.sessionToken = sessionToken;
|
|
270
288
|
(_a = this.onTokenChange) == null ? void 0 : _a.call(this, sessionToken);
|
|
@@ -282,6 +300,10 @@ var TagadaHeadlessBundle = (() => {
|
|
|
282
300
|
);
|
|
283
301
|
const session = this.normalizeSession(raw);
|
|
284
302
|
this._currentSession = session;
|
|
303
|
+
try {
|
|
304
|
+
(_b = this.onSession) == null ? void 0 : _b.call(this, session);
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
285
307
|
return session;
|
|
286
308
|
}
|
|
287
309
|
/**
|
|
@@ -295,6 +317,9 @@ var TagadaHeadlessBundle = (() => {
|
|
|
295
317
|
const lineItems = opts.items.map((i) => ({
|
|
296
318
|
variantId: i.variantId,
|
|
297
319
|
priceId: i.priceId,
|
|
320
|
+
...i.sellingPlanId !== void 0 ? { sellingPlanId: i.sellingPlanId } : {},
|
|
321
|
+
...i.trialDays !== void 0 ? { trialDays: i.trialDays } : {},
|
|
322
|
+
...i.trialPrice !== void 0 ? { trialPrice: i.trialPrice } : {},
|
|
298
323
|
quantity: i.quantity
|
|
299
324
|
}));
|
|
300
325
|
const body = {
|
|
@@ -303,6 +328,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
303
328
|
};
|
|
304
329
|
if (opts.returnUrl)
|
|
305
330
|
body.returnUrl = opts.returnUrl;
|
|
331
|
+
if (opts.funnelSessionId)
|
|
332
|
+
body.funnelSessionId = opts.funnelSessionId;
|
|
306
333
|
if ((_a = opts.discountCodes) == null ? void 0 : _a.length)
|
|
307
334
|
body.discountCodes = opts.discountCodes;
|
|
308
335
|
if (opts.metadata && Object.keys(opts.metadata).length > 0)
|
|
@@ -324,8 +351,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
324
351
|
body.customer = customerData;
|
|
325
352
|
}
|
|
326
353
|
const res = await this.http.post("/api/v1/checkout/session/init", body);
|
|
327
|
-
const
|
|
328
|
-
const sessionToken =
|
|
354
|
+
const url2 = new URL(res.checkoutUrl);
|
|
355
|
+
const sessionToken = url2.searchParams.get("token") ?? "";
|
|
329
356
|
this.sessionToken = sessionToken;
|
|
330
357
|
if (sessionToken)
|
|
331
358
|
(_c = this.onTokenChange) == null ? void 0 : _c.call(this, sessionToken);
|
|
@@ -366,8 +393,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
366
393
|
checkoutToken: session.checkoutToken,
|
|
367
394
|
sessionToken: session.sessionToken
|
|
368
395
|
});
|
|
369
|
-
const
|
|
370
|
-
return { ...session, url };
|
|
396
|
+
const url2 = `${origin}${checkoutPath}?${params.toString()}`;
|
|
397
|
+
return { ...session, url: url2 };
|
|
371
398
|
}
|
|
372
399
|
/**
|
|
373
400
|
* Read `checkoutToken` and session token from a URL.
|
|
@@ -392,10 +419,10 @@ var TagadaHeadlessBundle = (() => {
|
|
|
392
419
|
* );
|
|
393
420
|
* ```
|
|
394
421
|
*/
|
|
395
|
-
static parseTokensFromUrl(
|
|
396
|
-
if (typeof
|
|
422
|
+
static parseTokensFromUrl(url2) {
|
|
423
|
+
if (typeof url2 === "undefined" && typeof window === "undefined")
|
|
397
424
|
return null;
|
|
398
|
-
const href =
|
|
425
|
+
const href = url2 ?? window.location.href;
|
|
399
426
|
let parsed;
|
|
400
427
|
try {
|
|
401
428
|
parsed = new URL(href);
|
|
@@ -409,8 +436,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
409
436
|
return { checkoutToken, sessionToken };
|
|
410
437
|
}
|
|
411
438
|
/** Instance alias of {@link CheckoutModule.parseTokensFromUrl}. */
|
|
412
|
-
parseTokensFromUrl(
|
|
413
|
-
return _CheckoutModule.parseTokensFromUrl(
|
|
439
|
+
parseTokensFromUrl(url2) {
|
|
440
|
+
return _CheckoutModule.parseTokensFromUrl(url2);
|
|
414
441
|
}
|
|
415
442
|
/**
|
|
416
443
|
* Add or update cart items on an existing session (upsert by product).
|
|
@@ -434,6 +461,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
434
461
|
const lineItems = items.map((i) => ({
|
|
435
462
|
variantId: i.variantId,
|
|
436
463
|
priceId: i.priceId,
|
|
464
|
+
...i.sellingPlanId !== void 0 ? { sellingPlanId: i.sellingPlanId } : {},
|
|
437
465
|
quantity: i.quantity
|
|
438
466
|
}));
|
|
439
467
|
return this.http.post(
|
|
@@ -640,7 +668,13 @@ var TagadaHeadlessBundle = (() => {
|
|
|
640
668
|
unitAmount: amount,
|
|
641
669
|
totalAmount: amount * (li.quantity ?? 1),
|
|
642
670
|
currency: sessionCurrency ?? "USD",
|
|
643
|
-
imageUrl: variant.imageUrl ?? product.imageUrl ?? ""
|
|
671
|
+
imageUrl: variant.imageUrl ?? product.imageUrl ?? "",
|
|
672
|
+
...(price == null ? void 0 : price.recurring) ? {
|
|
673
|
+
recurring: {
|
|
674
|
+
interval: price.interval ?? "month",
|
|
675
|
+
intervalCount: price.intervalCount ?? 1
|
|
676
|
+
}
|
|
677
|
+
} : {}
|
|
644
678
|
};
|
|
645
679
|
});
|
|
646
680
|
const summaryItems = summary.items ?? [];
|
|
@@ -751,6 +785,407 @@ var TagadaHeadlessBundle = (() => {
|
|
|
751
785
|
return Boolean(((_a = address.line1) == null ? void 0 : _a.trim()) && ((_b = address.country) == null ? void 0 : _b.trim()));
|
|
752
786
|
}
|
|
753
787
|
|
|
788
|
+
// src/core/version.ts
|
|
789
|
+
var SDK_NAME = "headless";
|
|
790
|
+
var SDK_VERSION = "1.17.0";
|
|
791
|
+
|
|
792
|
+
// src/core/modules/track.ts
|
|
793
|
+
var CDN_URL = false ? "" : "https://cdn.jsdelivr.net/npm/@tagadapay/headless-sdk@1.17.0/dist/tagada-pixels.min.js";
|
|
794
|
+
function loadScript(src, isReady) {
|
|
795
|
+
if (isReady())
|
|
796
|
+
return Promise.resolve();
|
|
797
|
+
return new Promise((resolve, reject) => {
|
|
798
|
+
const script2 = document.createElement("script");
|
|
799
|
+
script2.src = src;
|
|
800
|
+
script2.async = true;
|
|
801
|
+
script2.onload = () => resolve();
|
|
802
|
+
script2.onerror = () => reject(new Error("runtime script failed to load"));
|
|
803
|
+
document.head.appendChild(script2);
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
async function loadPixels() {
|
|
807
|
+
if (typeof window === "undefined")
|
|
808
|
+
return null;
|
|
809
|
+
if (CDN_URL) {
|
|
810
|
+
const w = window;
|
|
811
|
+
if (w.TagadaPixels)
|
|
812
|
+
return w.TagadaPixels;
|
|
813
|
+
await loadScript(CDN_URL, () => Boolean(w.TagadaPixels));
|
|
814
|
+
return w.TagadaPixels ?? null;
|
|
815
|
+
}
|
|
816
|
+
return await import("../../pixels/index.js");
|
|
817
|
+
}
|
|
818
|
+
var FLAG_KEY = "__tgd_track";
|
|
819
|
+
var ANON_KEY = "__tgd_aid";
|
|
820
|
+
var SESSION_KEY = "__tgd_sid";
|
|
821
|
+
var QUEUE_LIMIT = 50;
|
|
822
|
+
var FLUSH_MS = 2e3;
|
|
823
|
+
var DEDUP_MS = 1e3;
|
|
824
|
+
var STEP_MEMORY = 64;
|
|
825
|
+
function toContents(items) {
|
|
826
|
+
if (!Array.isArray(items) || items.length === 0)
|
|
827
|
+
return void 0;
|
|
828
|
+
return items.map((item) => ({ id: item.variantId, quantity: item.quantity, item_price: item.unitAmount }));
|
|
829
|
+
}
|
|
830
|
+
function scalars(data) {
|
|
831
|
+
if (!data)
|
|
832
|
+
return void 0;
|
|
833
|
+
const out = {};
|
|
834
|
+
for (const [key, value] of Object.entries(data)) {
|
|
835
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
836
|
+
out[key] = value;
|
|
837
|
+
}
|
|
838
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
839
|
+
}
|
|
840
|
+
var STANDARD_EVENTS = {
|
|
841
|
+
lead: "Lead",
|
|
842
|
+
product_viewed: "ViewContent",
|
|
843
|
+
added_to_cart: "AddToCart"
|
|
844
|
+
};
|
|
845
|
+
function uuid() {
|
|
846
|
+
try {
|
|
847
|
+
return crypto.randomUUID();
|
|
848
|
+
} catch {
|
|
849
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
function toPixelsConfig(pixels) {
|
|
853
|
+
const out = {};
|
|
854
|
+
for (const pixel of pixels) {
|
|
855
|
+
const { provider, id, idKey, ...rest } = pixel;
|
|
856
|
+
(out[provider] ?? (out[provider] = [])).push({ ...rest, enabled: true, [idKey]: id, events: pixel.events ?? {} });
|
|
857
|
+
}
|
|
858
|
+
return out;
|
|
859
|
+
}
|
|
860
|
+
var TrackModule = class {
|
|
861
|
+
constructor(baseUrl, storeId, funnelKey) {
|
|
862
|
+
this.baseUrl = baseUrl;
|
|
863
|
+
this.storeId = storeId;
|
|
864
|
+
this.funnelKey = funnelKey;
|
|
865
|
+
this.records = [];
|
|
866
|
+
this.lastStep = /* @__PURE__ */ new Map();
|
|
867
|
+
this.signals = [];
|
|
868
|
+
this.currentStepId = null;
|
|
869
|
+
this.manifestHash = null;
|
|
870
|
+
this.loadedProviders = [];
|
|
871
|
+
this.configPromise = null;
|
|
872
|
+
this.corePromise = null;
|
|
873
|
+
this.enginePromise = null;
|
|
874
|
+
this.flushTimer = null;
|
|
875
|
+
this.listening = false;
|
|
876
|
+
}
|
|
877
|
+
// -- opt-in flag ----------------------------------------------------------
|
|
878
|
+
/**
|
|
879
|
+
* The flag is `<storeId>:<funnelKey>`. Only the storeId half arms it; the funnel half is DATA,
|
|
880
|
+
* read back by `flagFunnelKey()` so automatic events report the funnel the last `step()` named.
|
|
881
|
+
* A funnel-key mismatch never disarms tracking; only another tenant's storeId reads as disabled.
|
|
882
|
+
*/
|
|
883
|
+
flag() {
|
|
884
|
+
try {
|
|
885
|
+
return (localStorage.getItem(FLAG_KEY) ?? "").split(":");
|
|
886
|
+
} catch {
|
|
887
|
+
return [];
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
enabled() {
|
|
891
|
+
return this.flag()[0] === this.storeId;
|
|
892
|
+
}
|
|
893
|
+
flagFunnelKey() {
|
|
894
|
+
return this.flag()[1] || this.funnelKey;
|
|
895
|
+
}
|
|
896
|
+
/** Every automatic path is off under SSR and off without the flag. */
|
|
897
|
+
off() {
|
|
898
|
+
return typeof window === "undefined" || !this.enabled();
|
|
899
|
+
}
|
|
900
|
+
arm() {
|
|
901
|
+
try {
|
|
902
|
+
localStorage.setItem(FLAG_KEY, `${this.storeId}:${this.funnelKey}`);
|
|
903
|
+
} catch {
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
// -- public API -----------------------------------------------------------
|
|
907
|
+
step(stepId, data) {
|
|
908
|
+
if (typeof window === "undefined")
|
|
909
|
+
return;
|
|
910
|
+
this.arm();
|
|
911
|
+
const path = (data == null ? void 0 : data.path) ?? window.location.pathname;
|
|
912
|
+
const key = `${stepId}|${path}`;
|
|
913
|
+
const at = Date.now();
|
|
914
|
+
const previous = this.lastStep.get(key);
|
|
915
|
+
if (previous !== void 0 && at - previous < DEDUP_MS)
|
|
916
|
+
return;
|
|
917
|
+
this.remember(key, at);
|
|
918
|
+
this.currentStepId = stepId;
|
|
919
|
+
this.listen();
|
|
920
|
+
this.push({ kind: "step", stepId, at, path });
|
|
921
|
+
void this.pixels().then((engine) => engine == null ? void 0 : engine.pageView(path, { stepId }));
|
|
922
|
+
void this.core().then((t) => t == null ? void 0 : t.page({ step_id: stepId })).catch(() => void 0);
|
|
923
|
+
}
|
|
924
|
+
event(name, data) {
|
|
925
|
+
if (this.off())
|
|
926
|
+
return;
|
|
927
|
+
const stepId = this.currentStepId;
|
|
928
|
+
if (stepId === null)
|
|
929
|
+
return;
|
|
930
|
+
const standard = STANDARD_EVENTS[name];
|
|
931
|
+
const eventId = `${standard ?? name}_${uuid()}`;
|
|
932
|
+
this.push({ kind: "event", stepId, name, at: Date.now(), eventId, props: scalars(data) });
|
|
933
|
+
void this.pixels().then(
|
|
934
|
+
(engine) => standard ? engine == null ? void 0 : engine.track(standard, data, { stepId, eventId }) : engine == null ? void 0 : engine.trackCustom(name, data, { stepId })
|
|
935
|
+
);
|
|
936
|
+
void this.core().then((t) => t == null ? void 0 : t.track(name, { ...scalars(data) ?? {}, step_id: stepId, pixel_event_id: eventId })).catch(() => void 0);
|
|
937
|
+
}
|
|
938
|
+
/** Keep the dedup map to entries still inside the window, and never past `STEP_MEMORY`. */
|
|
939
|
+
remember(key, at) {
|
|
940
|
+
for (const [seen, when] of this.lastStep) {
|
|
941
|
+
if (at - when >= DEDUP_MS)
|
|
942
|
+
this.lastStep.delete(seen);
|
|
943
|
+
}
|
|
944
|
+
while (this.lastStep.size >= STEP_MEMORY) {
|
|
945
|
+
const oldest = this.lastStep.keys().next();
|
|
946
|
+
if (oldest.done === true)
|
|
947
|
+
break;
|
|
948
|
+
this.lastStep.delete(oldest.value);
|
|
949
|
+
}
|
|
950
|
+
this.lastStep.set(key, at);
|
|
951
|
+
}
|
|
952
|
+
identify(who) {
|
|
953
|
+
if (this.off())
|
|
954
|
+
return;
|
|
955
|
+
void this.pixels().then(
|
|
956
|
+
(engine) => engine == null ? void 0 : engine.identify({ email: who.email, phone: who.phone, externalId: who.customerId })
|
|
957
|
+
);
|
|
958
|
+
void this.core().then((t) => t == null ? void 0 : t.identify(who.customerId ?? null, { email: who.email, phone: who.phone, customerId: who.customerId })).catch(() => void 0);
|
|
959
|
+
}
|
|
960
|
+
consent(state) {
|
|
961
|
+
if (this.off())
|
|
962
|
+
return;
|
|
963
|
+
void this.pixels().then((engine) => engine == null ? void 0 : engine.consent(state));
|
|
964
|
+
}
|
|
965
|
+
async health() {
|
|
966
|
+
if (typeof window === "undefined")
|
|
967
|
+
return this.snapshot();
|
|
968
|
+
if (this.enabled())
|
|
969
|
+
await this.config();
|
|
970
|
+
return this.snapshot();
|
|
971
|
+
}
|
|
972
|
+
// -- internal hooks, called by the checkout and payment modules -----------
|
|
973
|
+
/** @internal */
|
|
974
|
+
noteCheckout(input) {
|
|
975
|
+
this.notePixel("InitiateCheckout", input.checkoutSessionId, input);
|
|
976
|
+
}
|
|
977
|
+
/** @internal */
|
|
978
|
+
notePaid(input) {
|
|
979
|
+
this.notePixel("Purchase", input.orderId, input);
|
|
980
|
+
}
|
|
981
|
+
/** The `eventId` formula is the server's `makeMetaEventId`, so Meta and TikTok dedup. */
|
|
982
|
+
notePixel(event, id, input) {
|
|
983
|
+
if (this.off())
|
|
984
|
+
return;
|
|
985
|
+
void this.pixels().then(
|
|
986
|
+
(engine) => {
|
|
987
|
+
var _a;
|
|
988
|
+
return engine == null ? void 0 : engine.track(
|
|
989
|
+
event,
|
|
990
|
+
{ value: input.amount, currency: input.currency, contents: input.items, num_items: (_a = input.items) == null ? void 0 : _a.length },
|
|
991
|
+
{ eventId: `${event}_${id}` }
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
/** @internal */
|
|
997
|
+
noteSignal(signal, value, detail) {
|
|
998
|
+
if (this.off())
|
|
999
|
+
return;
|
|
1000
|
+
this.signals.push({ signal, value, detail });
|
|
1001
|
+
this.listen();
|
|
1002
|
+
this.push({ kind: "signal", signal, value, detail });
|
|
1003
|
+
}
|
|
1004
|
+
// -- config, engine -------------------------------------------------------
|
|
1005
|
+
snapshot() {
|
|
1006
|
+
return {
|
|
1007
|
+
enabled: typeof window === "undefined" ? false : this.enabled(),
|
|
1008
|
+
storeId: this.storeId,
|
|
1009
|
+
funnelKey: this.flagFunnelKey(),
|
|
1010
|
+
sdk: { name: SDK_NAME, version: SDK_VERSION },
|
|
1011
|
+
manifestHash: this.manifestHash,
|
|
1012
|
+
pixels: { loaded: this.loadedProviders.length > 0, providers: [...this.loadedProviders] },
|
|
1013
|
+
signals: [...this.signals]
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* R4, once per page. Plain `fetch`, no header, no credentials — never `HttpClient`,
|
|
1018
|
+
* which adds `Content-Type` and `x-cms-token` and so preflights against a fixed allow-list.
|
|
1019
|
+
*/
|
|
1020
|
+
config() {
|
|
1021
|
+
if (this.configPromise !== null)
|
|
1022
|
+
return this.configPromise;
|
|
1023
|
+
const url2 = `${this.baseUrl}/api/public/v1/sdk/config?storeId=${encodeURIComponent(this.storeId)}&funnel=${encodeURIComponent(this.flagFunnelKey())}`;
|
|
1024
|
+
this.configPromise = (async () => {
|
|
1025
|
+
try {
|
|
1026
|
+
const response = await fetch(url2);
|
|
1027
|
+
if (!response.ok)
|
|
1028
|
+
return null;
|
|
1029
|
+
const config = await response.json();
|
|
1030
|
+
this.manifestHash = config.manifestHash || null;
|
|
1031
|
+
return config;
|
|
1032
|
+
} catch {
|
|
1033
|
+
return null;
|
|
1034
|
+
}
|
|
1035
|
+
})();
|
|
1036
|
+
return this.configPromise;
|
|
1037
|
+
}
|
|
1038
|
+
/** @internal R4 is reused; loading is allowed only when it opts this store in. */
|
|
1039
|
+
core() {
|
|
1040
|
+
if (typeof window === "undefined")
|
|
1041
|
+
return Promise.resolve(null);
|
|
1042
|
+
this.corePromise ?? (this.corePromise = (async () => {
|
|
1043
|
+
var _a, _b;
|
|
1044
|
+
try {
|
|
1045
|
+
const config = await this.config();
|
|
1046
|
+
if (!config || !config.collect && !config.experiments)
|
|
1047
|
+
return null;
|
|
1048
|
+
const base = this.baseUrl.replace(/\/+$/, "");
|
|
1049
|
+
const w = window;
|
|
1050
|
+
if (typeof ((_a = w.tgd) == null ? void 0 : _a.init) !== "function") {
|
|
1051
|
+
await loadScript(base + "/assets/js/tgd.js", () => {
|
|
1052
|
+
var _a2;
|
|
1053
|
+
return typeof ((_a2 = w.tgd) == null ? void 0 : _a2.init) === "function";
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
if (typeof ((_b = w.tgd) == null ? void 0 : _b.init) !== "function")
|
|
1057
|
+
return null;
|
|
1058
|
+
w.tgd.init({
|
|
1059
|
+
storeId: this.storeId,
|
|
1060
|
+
apiHost: config.collect ? new URL(config.collect.url).origin : base,
|
|
1061
|
+
bootstrap: this.bootstrap,
|
|
1062
|
+
_source: "headless",
|
|
1063
|
+
_manualPages: true
|
|
1064
|
+
});
|
|
1065
|
+
return w.tgd;
|
|
1066
|
+
} catch {
|
|
1067
|
+
return null;
|
|
1068
|
+
}
|
|
1069
|
+
})());
|
|
1070
|
+
return this.corePromise;
|
|
1071
|
+
}
|
|
1072
|
+
/** @internal Funnel navigation alone must not opt a site into tracking. */
|
|
1073
|
+
noteFunnelSession(funnelSessionId) {
|
|
1074
|
+
if (this.off())
|
|
1075
|
+
return;
|
|
1076
|
+
void this.core().then((t) => t == null ? void 0 : t._link(funnelSessionId)).catch(() => void 0);
|
|
1077
|
+
}
|
|
1078
|
+
pixels() {
|
|
1079
|
+
if (!this.enabled())
|
|
1080
|
+
return Promise.resolve(null);
|
|
1081
|
+
this.enginePromise ?? (this.enginePromise = this.startEngine());
|
|
1082
|
+
return this.enginePromise;
|
|
1083
|
+
}
|
|
1084
|
+
async startEngine() {
|
|
1085
|
+
var _a;
|
|
1086
|
+
try {
|
|
1087
|
+
const config = await this.config();
|
|
1088
|
+
if (config === null)
|
|
1089
|
+
return null;
|
|
1090
|
+
const module = await loadPixels();
|
|
1091
|
+
if (module === null)
|
|
1092
|
+
return null;
|
|
1093
|
+
const engine = module.createPixelEngine({
|
|
1094
|
+
pixels: toPixelsConfig(config.pixels ?? []),
|
|
1095
|
+
steps: config.steps,
|
|
1096
|
+
checkout: config.checkout,
|
|
1097
|
+
requireConsent: ((_a = config.consent) == null ? void 0 : _a.required) === true,
|
|
1098
|
+
onSignal: (signal) => this.onPixelSignal(signal)
|
|
1099
|
+
});
|
|
1100
|
+
await engine.init();
|
|
1101
|
+
this.loadedProviders = [...new Set((config.pixels ?? []).map((pixel) => pixel.provider))];
|
|
1102
|
+
return engine;
|
|
1103
|
+
} catch {
|
|
1104
|
+
return null;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
onPixelSignal(signal) {
|
|
1108
|
+
const detail = signal.detail ?? {};
|
|
1109
|
+
this.signals.push({ signal: signal.kind, value: signal.provider, detail });
|
|
1110
|
+
this.push({ kind: "signal", signal: signal.kind, value: signal.provider, detail });
|
|
1111
|
+
}
|
|
1112
|
+
// -- R5 queue -------------------------------------------------------------
|
|
1113
|
+
listen() {
|
|
1114
|
+
if (this.listening || typeof window === "undefined")
|
|
1115
|
+
return;
|
|
1116
|
+
this.listening = true;
|
|
1117
|
+
const onLeave = (event) => {
|
|
1118
|
+
if (event.type === "visibilitychange" && document.visibilityState !== "hidden")
|
|
1119
|
+
return;
|
|
1120
|
+
this.flush();
|
|
1121
|
+
};
|
|
1122
|
+
window.addEventListener("pagehide", onLeave);
|
|
1123
|
+
window.addEventListener("visibilitychange", onLeave);
|
|
1124
|
+
}
|
|
1125
|
+
push(record) {
|
|
1126
|
+
if (!this.enabled())
|
|
1127
|
+
return;
|
|
1128
|
+
this.records.push(record);
|
|
1129
|
+
if (this.records.length >= QUEUE_LIMIT) {
|
|
1130
|
+
this.flush();
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
if (this.flushTimer === null)
|
|
1134
|
+
this.flushTimer = setTimeout(() => this.flush(), FLUSH_MS);
|
|
1135
|
+
}
|
|
1136
|
+
/** `localStorage` is an undeclared identifier in Node, so it is read inside the try. */
|
|
1137
|
+
identifier(scope, key) {
|
|
1138
|
+
try {
|
|
1139
|
+
const store = scope === "local" ? localStorage : sessionStorage;
|
|
1140
|
+
const existing = store.getItem(key);
|
|
1141
|
+
if (existing)
|
|
1142
|
+
return existing;
|
|
1143
|
+
const fresh = uuid();
|
|
1144
|
+
store.setItem(key, fresh);
|
|
1145
|
+
return fresh;
|
|
1146
|
+
} catch {
|
|
1147
|
+
return uuid();
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
flush() {
|
|
1151
|
+
if (this.flushTimer !== null) {
|
|
1152
|
+
clearTimeout(this.flushTimer);
|
|
1153
|
+
this.flushTimer = null;
|
|
1154
|
+
}
|
|
1155
|
+
if (this.records.length === 0)
|
|
1156
|
+
return;
|
|
1157
|
+
const records = this.records.splice(0, QUEUE_LIMIT);
|
|
1158
|
+
const payload = {
|
|
1159
|
+
storeId: this.storeId,
|
|
1160
|
+
funnelKey: this.flagFunnelKey(),
|
|
1161
|
+
sdk: { name: SDK_NAME, version: SDK_VERSION },
|
|
1162
|
+
anonymousId: this.identifier("local", ANON_KEY),
|
|
1163
|
+
sessionId: this.identifier("session", SESSION_KEY),
|
|
1164
|
+
records
|
|
1165
|
+
};
|
|
1166
|
+
if (this.manifestHash !== null)
|
|
1167
|
+
payload.manifestHash = this.manifestHash;
|
|
1168
|
+
const body = JSON.stringify(payload);
|
|
1169
|
+
const url2 = `${this.baseUrl}/api/public/v1/sdk/events`;
|
|
1170
|
+
try {
|
|
1171
|
+
if (typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function") {
|
|
1172
|
+
if (navigator.sendBeacon(url2, new Blob([body], { type: "text/plain;charset=UTF-8" })))
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
} catch {
|
|
1176
|
+
}
|
|
1177
|
+
try {
|
|
1178
|
+
void fetch(url2, {
|
|
1179
|
+
method: "POST",
|
|
1180
|
+
body,
|
|
1181
|
+
keepalive: true,
|
|
1182
|
+
headers: { "content-type": "text/plain;charset=UTF-8" }
|
|
1183
|
+
}).catch(() => void 0);
|
|
1184
|
+
} catch {
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
|
|
754
1189
|
// src/core/modules/payment.ts
|
|
755
1190
|
var EXPRESS_METHOD_TYPES = /* @__PURE__ */ new Set(["apple_pay", "google_pay", "paypal", "klarna", "klarna_express", "link"]);
|
|
756
1191
|
function paymentMethodListEntryToConfig(entry) {
|
|
@@ -775,11 +1210,13 @@ var TagadaHeadlessBundle = (() => {
|
|
|
775
1210
|
};
|
|
776
1211
|
}
|
|
777
1212
|
var PaymentModule = class {
|
|
778
|
-
constructor(http, storeId, environment, checkout) {
|
|
1213
|
+
constructor(http, storeId, environment, checkout, onPaid, onSignal) {
|
|
779
1214
|
this.http = http;
|
|
780
1215
|
this.storeId = storeId;
|
|
781
1216
|
this.environment = environment;
|
|
782
1217
|
this.checkout = checkout;
|
|
1218
|
+
this.onPaid = onPaid;
|
|
1219
|
+
this.onSignal = onSignal;
|
|
783
1220
|
/**
|
|
784
1221
|
* Last payment setup seen by `getPaymentSetup` — lets `processApplePay`
|
|
785
1222
|
* resolve the domain's Apple Pay registration (BYOK / platform-integrator)
|
|
@@ -847,7 +1284,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
847
1284
|
* filtered to only those available in the current browser.
|
|
848
1285
|
*/
|
|
849
1286
|
async getExpressMethods(checkoutSessionId, opts) {
|
|
850
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1287
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
851
1288
|
const setup = await this.getPaymentSetup(checkoutSessionId, opts);
|
|
852
1289
|
const result = {};
|
|
853
1290
|
for (const [key, config] of Object.entries(setup)) {
|
|
@@ -865,12 +1302,15 @@ var TagadaHeadlessBundle = (() => {
|
|
|
865
1302
|
result.applePay = { ...base2, type: "apple_pay", available: !!hasApplePay };
|
|
866
1303
|
}
|
|
867
1304
|
if ((_d = config.methods.google_pay) == null ? void 0 : _d.enabled) {
|
|
1305
|
+
if (typeof window !== "undefined" && !("PaymentRequest" in window)) {
|
|
1306
|
+
(_e = this.onSignal) == null ? void 0 : _e.call(this, "googlePay", { reason: "no-payment-request-api" });
|
|
1307
|
+
}
|
|
868
1308
|
result.googlePay = { ...base2, type: "google_pay" };
|
|
869
1309
|
}
|
|
870
|
-
if ((
|
|
1310
|
+
if ((_f = config.methods.link) == null ? void 0 : _f.enabled) {
|
|
871
1311
|
result.link = { ...base2, type: "link" };
|
|
872
1312
|
}
|
|
873
|
-
if ((
|
|
1313
|
+
if ((_g = config.methods.klarna_express) == null ? void 0 : _g.enabled) {
|
|
874
1314
|
result.klarna = { ...base2, type: "klarna_express" };
|
|
875
1315
|
}
|
|
876
1316
|
continue;
|
|
@@ -886,9 +1326,12 @@ var TagadaHeadlessBundle = (() => {
|
|
|
886
1326
|
metadata: config.metadata
|
|
887
1327
|
};
|
|
888
1328
|
if (method === "apple_pay" || config.type === "apple_pay") {
|
|
889
|
-
const hasApplePay = typeof window !== "undefined" && "ApplePaySession" in window && ((
|
|
1329
|
+
const hasApplePay = typeof window !== "undefined" && "ApplePaySession" in window && ((_i = (_h = window.ApplePaySession) == null ? void 0 : _h.canMakePayments) == null ? void 0 : _i.call(_h));
|
|
890
1330
|
result.applePay = { ...base, available: !!hasApplePay };
|
|
891
1331
|
} else if (method === "google_pay" || config.type === "google_pay") {
|
|
1332
|
+
if (typeof window !== "undefined" && !("PaymentRequest" in window)) {
|
|
1333
|
+
(_j = this.onSignal) == null ? void 0 : _j.call(this, "googlePay", { reason: "no-payment-request-api" });
|
|
1334
|
+
}
|
|
892
1335
|
result.googlePay = base;
|
|
893
1336
|
} else if (method === "paypal") {
|
|
894
1337
|
result.paypal = base;
|
|
@@ -1287,14 +1730,15 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1287
1730
|
* don't need to re-pay.
|
|
1288
1731
|
*/
|
|
1289
1732
|
async finalize(input, opts) {
|
|
1290
|
-
var _a, _b;
|
|
1733
|
+
var _a, _b, _c;
|
|
1291
1734
|
const payment = input.payment;
|
|
1292
1735
|
const returnUrl = (opts == null ? void 0 : opts.returnUrl) ?? (typeof window !== "undefined" ? window.location.href : void 0);
|
|
1293
1736
|
if (payment.status === "succeeded") {
|
|
1737
|
+
this.emitPaid((_a = input.order) == null ? void 0 : _a.id, payment);
|
|
1294
1738
|
return { status: "succeeded", payment, order: input.order };
|
|
1295
1739
|
}
|
|
1296
1740
|
if (payment.status === "failed" || payment.status === "declined") {
|
|
1297
|
-
const msg = ((
|
|
1741
|
+
const msg = ((_b = payment.requireActionData) == null ? void 0 : _b.message) || ((_c = payment.requireActionData) == null ? void 0 : _c.errorCode) || `Payment ${payment.status}`;
|
|
1298
1742
|
return { status: "failed", error: msg, payment };
|
|
1299
1743
|
}
|
|
1300
1744
|
if (payment.requireAction && payment.requireAction !== "none" && payment.requireActionData) {
|
|
@@ -1345,15 +1789,15 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1345
1789
|
if (typeof window === "undefined" && !(opts == null ? void 0 : opts.url))
|
|
1346
1790
|
return null;
|
|
1347
1791
|
const href = (opts == null ? void 0 : opts.url) ?? window.location.href;
|
|
1348
|
-
let
|
|
1792
|
+
let url2;
|
|
1349
1793
|
try {
|
|
1350
|
-
|
|
1794
|
+
url2 = new URL(href);
|
|
1351
1795
|
} catch {
|
|
1352
1796
|
return null;
|
|
1353
1797
|
}
|
|
1354
|
-
const action =
|
|
1355
|
-
const actionStatus =
|
|
1356
|
-
const paymentId =
|
|
1798
|
+
const action = url2.searchParams.get("paymentAction");
|
|
1799
|
+
const actionStatus = url2.searchParams.get("paymentActionStatus");
|
|
1800
|
+
const paymentId = url2.searchParams.get("paymentId");
|
|
1357
1801
|
if (action !== "requireAction" || actionStatus !== "completed" || !paymentId) {
|
|
1358
1802
|
return null;
|
|
1359
1803
|
}
|
|
@@ -1458,8 +1902,8 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1458
1902
|
extractRedirect(payment, actionData) {
|
|
1459
1903
|
var _a, _b;
|
|
1460
1904
|
const redirect = (_a = actionData.metadata) == null ? void 0 : _a.redirect;
|
|
1461
|
-
const
|
|
1462
|
-
if (!
|
|
1905
|
+
const url2 = (redirect == null ? void 0 : redirect.redirectUrl) || actionData.redirectUrl;
|
|
1906
|
+
if (!url2) {
|
|
1463
1907
|
return {
|
|
1464
1908
|
status: "failed",
|
|
1465
1909
|
error: `Payment requires action (${actionData.type}) but no redirect URL was provided`,
|
|
@@ -1468,7 +1912,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1468
1912
|
}
|
|
1469
1913
|
return {
|
|
1470
1914
|
status: "requires_redirect",
|
|
1471
|
-
redirectUrl:
|
|
1915
|
+
redirectUrl: url2,
|
|
1472
1916
|
method: ((_b = redirect == null ? void 0 : redirect.method) == null ? void 0 : _b.toUpperCase()) || "GET",
|
|
1473
1917
|
postData: redirect == null ? void 0 : redirect.data,
|
|
1474
1918
|
paymentId: payment.id
|
|
@@ -1528,6 +1972,7 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1528
1972
|
* Also handles new requireAction that may appear during polling.
|
|
1529
1973
|
*/
|
|
1530
1974
|
async pollUntilDone(paymentId, opts) {
|
|
1975
|
+
var _a;
|
|
1531
1976
|
const interval = (opts == null ? void 0 : opts.intervalMs) ?? 1500;
|
|
1532
1977
|
const timeout = (opts == null ? void 0 : opts.timeoutMs) ?? 6e4;
|
|
1533
1978
|
const start = Date.now();
|
|
@@ -1546,6 +1991,9 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1546
1991
|
continue;
|
|
1547
1992
|
}
|
|
1548
1993
|
if (status.status === "succeeded" || status.status === "pending" && status.subStatus === "authorized") {
|
|
1994
|
+
if (status.status === "succeeded") {
|
|
1995
|
+
this.emitPaid((_a = status.order) == null ? void 0 : _a.id, status);
|
|
1996
|
+
}
|
|
1549
1997
|
return { status: "succeeded", payment: status, order: status.order };
|
|
1550
1998
|
}
|
|
1551
1999
|
if (status.status === "failed" || status.status === "declined") {
|
|
@@ -1581,260 +2029,113 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1581
2029
|
return null;
|
|
1582
2030
|
}
|
|
1583
2031
|
}
|
|
2032
|
+
/** Tracking hook. Never throws, never awaits: a pixel must not be able to break a payment. */
|
|
2033
|
+
emitPaid(orderId, payment) {
|
|
2034
|
+
var _a;
|
|
2035
|
+
if (!orderId || !this.onPaid)
|
|
2036
|
+
return;
|
|
2037
|
+
try {
|
|
2038
|
+
const session = (_a = this.checkout) == null ? void 0 : _a.getCurrentSession();
|
|
2039
|
+
this.onPaid({
|
|
2040
|
+
orderId,
|
|
2041
|
+
amount: payment.amount,
|
|
2042
|
+
currency: payment.currency,
|
|
2043
|
+
items: toContents(session == null ? void 0 : session.items)
|
|
2044
|
+
});
|
|
2045
|
+
} catch {
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
1584
2048
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1585
2049
|
async loadCoreJs() {
|
|
1586
2050
|
try {
|
|
1587
2051
|
return await import("@tagadapay/core-js");
|
|
1588
|
-
} catch {
|
|
1589
|
-
|
|
2052
|
+
} catch (cause) {
|
|
2053
|
+
const error = new Error(
|
|
1590
2054
|
"This method requires @tagadapay/core-js. Install it: npm install @tagadapay/core-js"
|
|
1591
2055
|
);
|
|
2056
|
+
error.cause = cause;
|
|
2057
|
+
throw error;
|
|
1592
2058
|
}
|
|
1593
2059
|
}
|
|
1594
2060
|
};
|
|
1595
2061
|
|
|
2062
|
+
// src/core/modules/lazyCommerce.ts
|
|
2063
|
+
var script = typeof document === "undefined" ? null : document.currentScript;
|
|
2064
|
+
var url = (script == null ? void 0 : script.src) ? new URL("tagada-headless-commerce.min.js", script.src).href : "https://cdn.jsdelivr.net/npm/@tagadapay/headless-sdk@1.17.0/dist/tagada-headless-commerce.min.js";
|
|
2065
|
+
var loading;
|
|
2066
|
+
function loadCommerce() {
|
|
2067
|
+
if (window.TagadaHeadlessCommerce)
|
|
2068
|
+
return Promise.resolve(window.TagadaHeadlessCommerce);
|
|
2069
|
+
if (!loading)
|
|
2070
|
+
loading = new Promise((resolve, reject) => {
|
|
2071
|
+
const element = document.createElement("script");
|
|
2072
|
+
element.src = url;
|
|
2073
|
+
element.async = true;
|
|
2074
|
+
if (script == null ? void 0 : script.nonce)
|
|
2075
|
+
element.nonce = script.nonce;
|
|
2076
|
+
element.addEventListener("load", () => window.TagadaHeadlessCommerce ? resolve(window.TagadaHeadlessCommerce) : reject(new Error("Commerce bundle did not initialize")));
|
|
2077
|
+
element.addEventListener("error", () => {
|
|
2078
|
+
element.remove();
|
|
2079
|
+
reject(new Error("Unable to load commerce bundle"));
|
|
2080
|
+
});
|
|
2081
|
+
document.head.appendChild(element);
|
|
2082
|
+
}).catch((error) => {
|
|
2083
|
+
loading = void 0;
|
|
2084
|
+
throw error;
|
|
2085
|
+
});
|
|
2086
|
+
return loading;
|
|
2087
|
+
}
|
|
2088
|
+
|
|
1596
2089
|
// src/core/modules/offers.ts
|
|
1597
2090
|
var OffersModule = class {
|
|
1598
|
-
constructor(
|
|
1599
|
-
this.
|
|
1600
|
-
this.storeId = storeId;
|
|
1601
|
-
this.payment = payment;
|
|
1602
|
-
}
|
|
1603
|
-
// ---------------------------------------------------------------------------
|
|
1604
|
-
// Offer loading
|
|
1605
|
-
// ---------------------------------------------------------------------------
|
|
1606
|
-
/** Get a single offer by ID. */
|
|
1607
|
-
async getOffer(offerId) {
|
|
1608
|
-
return this.http.get(`/api/v1/offers/${offerId}`);
|
|
2091
|
+
constructor(...args) {
|
|
2092
|
+
this.args = args;
|
|
1609
2093
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
if (opts == null ? void 0 : opts.type)
|
|
1616
|
-
queryParts.push(`type=${encodeURIComponent(opts.type)}`);
|
|
1617
|
-
if ((_a = opts == null ? void 0 : opts.ids) == null ? void 0 : _a.length) {
|
|
1618
|
-
for (const id of opts.ids)
|
|
1619
|
-
queryParts.push(`ids=${encodeURIComponent(id)}`);
|
|
1620
|
-
}
|
|
1621
|
-
if (queryParts.length)
|
|
1622
|
-
url += `?${queryParts.join("&")}`;
|
|
1623
|
-
const res = await this.http.get(url);
|
|
1624
|
-
return res.offers ?? [];
|
|
1625
|
-
}
|
|
1626
|
-
// ---------------------------------------------------------------------------
|
|
1627
|
-
// Preview & pay (one-click upsell flow from plugin-sdk)
|
|
1628
|
-
// ---------------------------------------------------------------------------
|
|
1629
|
-
/** Preview offer pricing. Returns line items with amounts and totals. */
|
|
1630
|
-
async previewOffer(opts) {
|
|
1631
|
-
return this.http.post(`/api/v1/offers/${opts.offerId}/preview`, {
|
|
1632
|
-
offerId: opts.offerId,
|
|
1633
|
-
currency: opts.currency ?? "",
|
|
1634
|
-
lineItems: opts.lineItems
|
|
1635
|
-
});
|
|
1636
|
-
}
|
|
1637
|
-
/**
|
|
1638
|
-
* Pay a previously previewed offer (one-click charge).
|
|
1639
|
-
* Used after a main order so the stored payment instrument is reused.
|
|
1640
|
-
*
|
|
1641
|
-
* **Low-level API.** Returns the raw `OfferPayResult` — `requireAction`,
|
|
1642
|
-
* polling, and 3DS redirects are NOT handled. For most cases, use
|
|
1643
|
-
* {@link processOfferPayment} which orchestrates the full lifecycle.
|
|
1644
|
-
*/
|
|
1645
|
-
async payPreviewedOffer(opts) {
|
|
1646
|
-
return this.http.post(`/api/v1/offers/${opts.offerId}/pay-preview`, {
|
|
1647
|
-
offerId: opts.offerId,
|
|
1648
|
-
currency: opts.currency ?? "",
|
|
1649
|
-
lineItems: opts.lineItems,
|
|
1650
|
-
returnUrl: opts.returnUrl ?? (typeof window !== "undefined" ? window.location.href : ""),
|
|
1651
|
-
mainOrderId: opts.mainOrderId,
|
|
1652
|
-
paymentInstrumentId: opts.paymentInstrumentId
|
|
1653
|
-
});
|
|
1654
|
-
}
|
|
1655
|
-
/**
|
|
1656
|
-
* One-click upsell with full lifecycle handling.
|
|
1657
|
-
*
|
|
1658
|
-
* Like `payment.processPayment()` but for previewed offers: charges the
|
|
1659
|
-
* stored instrument from `mainOrderId`, runs any 3DS challenge or bank
|
|
1660
|
-
* redirect, polls until terminal, and returns a typed
|
|
1661
|
-
* `ProcessPaymentResult` (`succeeded` / `requires_redirect` /
|
|
1662
|
-
* `failed` / `pending`).
|
|
1663
|
-
*
|
|
1664
|
-
* Use this instead of the lower-level `payPreviewedOffer()` whenever you
|
|
1665
|
-
* don't need to inspect the raw `OfferPayResult` shape — which is most
|
|
1666
|
-
* of the time.
|
|
1667
|
-
*
|
|
1668
|
-
* @example
|
|
1669
|
-
* ```ts
|
|
1670
|
-
* const result = await tagada.offers.processOfferPayment({
|
|
1671
|
-
* offerId: 'offer_xxx',
|
|
1672
|
-
* mainOrderId: order.id,
|
|
1673
|
-
* returnUrl: window.location.href,
|
|
1674
|
-
* });
|
|
1675
|
-
*
|
|
1676
|
-
* switch (result.status) {
|
|
1677
|
-
* case 'succeeded':
|
|
1678
|
-
* window.location.href = '/upsell-2';
|
|
1679
|
-
* break;
|
|
1680
|
-
* case 'requires_redirect':
|
|
1681
|
-
* window.location.href = result.redirectUrl;
|
|
1682
|
-
* break;
|
|
1683
|
-
* case 'failed':
|
|
1684
|
-
* showError(result.error);
|
|
1685
|
-
* break;
|
|
1686
|
-
* }
|
|
1687
|
-
* ```
|
|
1688
|
-
*/
|
|
1689
|
-
async processOfferPayment(opts) {
|
|
1690
|
-
if (!this.payment) {
|
|
1691
|
-
throw new Error(
|
|
1692
|
-
"OffersModule: no PaymentModule injected. Use createHeadlessClient() instead of constructing OffersModule directly."
|
|
1693
|
-
);
|
|
1694
|
-
}
|
|
1695
|
-
const returnUrl = opts.returnUrl ?? (typeof window !== "undefined" ? window.location.href : void 0);
|
|
1696
|
-
const payResult = await this.payPreviewedOffer({ ...opts, returnUrl });
|
|
1697
|
-
return this.payment.finalize(
|
|
1698
|
-
{ payment: payResult.payment, order: payResult.order },
|
|
1699
|
-
{ returnUrl }
|
|
1700
|
-
);
|
|
1701
|
-
}
|
|
1702
|
-
// ---------------------------------------------------------------------------
|
|
1703
|
-
// Order bumps (checkout-session scoped)
|
|
1704
|
-
// ---------------------------------------------------------------------------
|
|
1705
|
-
/** Toggle an order bump on/off within a checkout session. */
|
|
1706
|
-
async toggleOrderBump(opts) {
|
|
1707
|
-
return this.http.post(
|
|
1708
|
-
`/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`,
|
|
1709
|
-
{
|
|
1710
|
-
orderBumpOfferId: opts.orderBumpOfferId,
|
|
1711
|
-
selected: opts.selected
|
|
1712
|
-
}
|
|
1713
|
-
);
|
|
1714
|
-
}
|
|
1715
|
-
// ---------------------------------------------------------------------------
|
|
1716
|
-
// Post-purchase offers (order-scoped)
|
|
1717
|
-
// ---------------------------------------------------------------------------
|
|
1718
|
-
/** List post-purchase offers for an order. */
|
|
1719
|
-
async listPostPurchaseOffers(orderId) {
|
|
1720
|
-
const res = await this.http.get(`/api/v1/post-purchase/${orderId}/offers`);
|
|
1721
|
-
return Array.isArray(res) ? res : [];
|
|
1722
|
-
}
|
|
1723
|
-
/** Accept a post-purchase offer. */
|
|
1724
|
-
async acceptPostPurchaseOffer(opts) {
|
|
1725
|
-
return this.http.post(
|
|
1726
|
-
`/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`,
|
|
1727
|
-
{ items: opts.items ?? [] }
|
|
1728
|
-
);
|
|
1729
|
-
}
|
|
1730
|
-
/** Decline a post-purchase offer. */
|
|
1731
|
-
async declinePostPurchaseOffer(opts) {
|
|
1732
|
-
return this.http.post(
|
|
1733
|
-
`/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`
|
|
1734
|
-
);
|
|
2094
|
+
load() {
|
|
2095
|
+
return this.instance || (this.instance = loadCommerce().then((m) => new m.OffersModule(...this.args)).catch((e) => {
|
|
2096
|
+
this.instance = void 0;
|
|
2097
|
+
throw e;
|
|
2098
|
+
}));
|
|
1735
2099
|
}
|
|
1736
2100
|
};
|
|
2101
|
+
for (const method of ["getOffer", "listOffers", "previewOffer", "enterFunnelStep", "payPreviewedOffer", "processOfferPayment", "toggleOrderBump", "listPostPurchaseOffers", "acceptPostPurchaseOffer", "declinePostPurchaseOffer"])
|
|
2102
|
+
OffersModule.prototype[method] = function(...args) {
|
|
2103
|
+
return this.load().then((instance) => instance[method](...args));
|
|
2104
|
+
};
|
|
1737
2105
|
|
|
1738
2106
|
// src/core/modules/customer.ts
|
|
1739
2107
|
var CustomerModule = class {
|
|
1740
|
-
constructor(
|
|
1741
|
-
this.
|
|
1742
|
-
this.storeId = storeId;
|
|
1743
|
-
}
|
|
1744
|
-
/** Get customer profile by ID. */
|
|
1745
|
-
async getProfile(customerId) {
|
|
1746
|
-
const res = await this.http.get(
|
|
1747
|
-
`/api/v1/customers/${customerId}`,
|
|
1748
|
-
{ params: { storeId: this.storeId } }
|
|
1749
|
-
);
|
|
1750
|
-
return res.customer;
|
|
1751
|
-
}
|
|
1752
|
-
/** Get customer profile by email. */
|
|
1753
|
-
async getByEmail(email) {
|
|
1754
|
-
try {
|
|
1755
|
-
const res = await this.http.get(
|
|
1756
|
-
"/api/v1/customers/by-email",
|
|
1757
|
-
{ params: { email, storeId: this.storeId } }
|
|
1758
|
-
);
|
|
1759
|
-
return res.customer;
|
|
1760
|
-
} catch {
|
|
1761
|
-
return null;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
/** Update customer profile fields. */
|
|
1765
|
-
async updateProfile(customerId, data) {
|
|
1766
|
-
const res = await this.http.patch(
|
|
1767
|
-
`/api/v1/customers/${customerId}`,
|
|
1768
|
-
{ storeId: this.storeId, ...data }
|
|
1769
|
-
);
|
|
1770
|
-
return res.customer;
|
|
1771
|
-
}
|
|
1772
|
-
/** List orders for a customer. */
|
|
1773
|
-
async getOrders(customerId, opts) {
|
|
1774
|
-
return this.http.get(
|
|
1775
|
-
`/api/v1/customers/${customerId}/orders`,
|
|
1776
|
-
{ params: { storeId: this.storeId, limit: opts == null ? void 0 : opts.limit, offset: opts == null ? void 0 : opts.offset } }
|
|
1777
|
-
);
|
|
1778
|
-
}
|
|
1779
|
-
/**
|
|
1780
|
-
* Get a single order by ID.
|
|
1781
|
-
*
|
|
1782
|
-
* **Thank-you pages:** accepted one-click upsells create *child orders*
|
|
1783
|
-
* (`metadata.mainOrderId` = this order's id) that land asynchronously —
|
|
1784
|
-
* the first fetch right after an accept usually misses them. Pass
|
|
1785
|
-
* `waitForRelatedOrders: true` to poll until `order.relatedOrders` is
|
|
1786
|
-
* non-empty or the timeout elapses. On timeout the latest snapshot is
|
|
1787
|
-
* returned (never throws), so an order with no accepted upsell simply
|
|
1788
|
-
* comes back with an empty `relatedOrders` after `timeoutMs`.
|
|
1789
|
-
*
|
|
1790
|
-
* @example
|
|
1791
|
-
* ```ts
|
|
1792
|
-
* // Thank-you page: show the main order AND the upsells
|
|
1793
|
-
* const order = await tagada.customer.getOrder(orderId, {
|
|
1794
|
-
* waitForRelatedOrders: true,
|
|
1795
|
-
* });
|
|
1796
|
-
* renderOrders([order, ...(order.relatedOrders ?? [])]);
|
|
1797
|
-
* ```
|
|
1798
|
-
*/
|
|
1799
|
-
async getOrder(orderId, opts) {
|
|
1800
|
-
var _a, _b;
|
|
1801
|
-
const fetchOrder = async () => {
|
|
1802
|
-
const res = await this.http.get(`/api/v1/orders/${orderId}`, {
|
|
1803
|
-
params: { storeId: this.storeId }
|
|
1804
|
-
});
|
|
1805
|
-
return res.order;
|
|
1806
|
-
};
|
|
1807
|
-
let order = await fetchOrder();
|
|
1808
|
-
if (!(opts == null ? void 0 : opts.waitForRelatedOrders) || ((_a = order.relatedOrders) == null ? void 0 : _a.length))
|
|
1809
|
-
return order;
|
|
1810
|
-
const timeoutMs = opts.timeoutMs ?? 8e3;
|
|
1811
|
-
const intervalMs = opts.intervalMs ?? 2e3;
|
|
1812
|
-
const deadline = Date.now() + timeoutMs;
|
|
1813
|
-
while (Date.now() < deadline) {
|
|
1814
|
-
await new Promise((resolve) => setTimeout(resolve, Math.min(intervalMs, Math.max(0, deadline - Date.now()))));
|
|
1815
|
-
order = await fetchOrder();
|
|
1816
|
-
if ((_b = order.relatedOrders) == null ? void 0 : _b.length)
|
|
1817
|
-
return order;
|
|
1818
|
-
}
|
|
1819
|
-
return order;
|
|
2108
|
+
constructor(...args) {
|
|
2109
|
+
this.args = args;
|
|
1820
2110
|
}
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
);
|
|
1827
|
-
return res.subscriptions;
|
|
2111
|
+
load() {
|
|
2112
|
+
return this.instance || (this.instance = loadCommerce().then((m) => new m.CustomerModule(...this.args)).catch((e) => {
|
|
2113
|
+
this.instance = void 0;
|
|
2114
|
+
throw e;
|
|
2115
|
+
}));
|
|
1828
2116
|
}
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
2117
|
+
};
|
|
2118
|
+
for (const method of ["getProfile", "getByEmail", "updateProfile", "getOrders", "getOrder", "getSubscriptions", "getSubscription", "pauseSubscription", "resumeSubscription", "skipSubscription", "rescheduleSubscription", "updateSubscriptionQuantity", "changeSubscriptionFrequency", "swapSubscriptionProduct", "updateSubscriptionPaymentMethod", "cancelSubscription"])
|
|
2119
|
+
CustomerModule.prototype[method] = function(...args) {
|
|
2120
|
+
return this.load().then((instance) => instance[method](...args));
|
|
2121
|
+
};
|
|
2122
|
+
|
|
2123
|
+
// src/core/modules/portal/index.ts
|
|
2124
|
+
var CustomerPortalModule = class {
|
|
2125
|
+
constructor(...args) {
|
|
2126
|
+
this.args = args;
|
|
2127
|
+
}
|
|
2128
|
+
load() {
|
|
2129
|
+
return this.instance || (this.instance = loadCommerce().then((m) => new m.CustomerPortalModule(...this.args)).catch((e) => {
|
|
2130
|
+
this.instance = void 0;
|
|
2131
|
+
throw e;
|
|
2132
|
+
}));
|
|
1836
2133
|
}
|
|
1837
2134
|
};
|
|
2135
|
+
for (const method of ["requestCode", "verifyCode", "getConfig", "getMe", "cancelFlow", "acceptCancelOffer", "switchOption", "getOffer", "acceptOffer", "addToNextOrder", "getCredits", "redeemCredits", "buyCreditPack", "requestEmailChangeCode", "updateProfile", "saveAddress", "removeAddress", "setDefaultAddress", "addCard", "removeCard", "setDefaultPaymentMethod", "retryPayment", "buyAgain", "joinMembership", "buyNow", "sendNow", "reactivateSubscription", "setSubscriptionCard", "setSubscriptionAddress", "skipDate", "unskipDate"])
|
|
2136
|
+
CustomerPortalModule.prototype[method] = function(...args) {
|
|
2137
|
+
return this.load().then((instance) => instance[method](...args));
|
|
2138
|
+
};
|
|
1838
2139
|
|
|
1839
2140
|
// src/core/modules/catalog.ts
|
|
1840
2141
|
var CatalogModule = class {
|
|
@@ -1876,14 +2177,15 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1876
2177
|
|
|
1877
2178
|
// src/core/modules/funnel.ts
|
|
1878
2179
|
var FunnelModule = class {
|
|
1879
|
-
constructor(http, storeId, checkout, accountId) {
|
|
2180
|
+
constructor(http, storeId, checkout, accountId, onFunnelSession) {
|
|
1880
2181
|
this.http = http;
|
|
1881
2182
|
this.storeId = storeId;
|
|
1882
2183
|
this.checkout = checkout;
|
|
1883
2184
|
this.accountId = accountId;
|
|
2185
|
+
this.onFunnelSession = onFunnelSession;
|
|
1884
2186
|
}
|
|
1885
2187
|
async navigate(input) {
|
|
1886
|
-
var _a;
|
|
2188
|
+
var _a, _b;
|
|
1887
2189
|
const session = this.checkout.getCurrentSession();
|
|
1888
2190
|
if (!session) {
|
|
1889
2191
|
throw new TagadaError(
|
|
@@ -1906,14 +2208,18 @@ var TagadaHeadlessBundle = (() => {
|
|
|
1906
2208
|
accountId,
|
|
1907
2209
|
currentUrl
|
|
1908
2210
|
});
|
|
1909
|
-
|
|
2211
|
+
try {
|
|
2212
|
+
(_b = this.onFunnelSession) == null ? void 0 : _b.call(this, funnelSessionId);
|
|
2213
|
+
} catch {
|
|
2214
|
+
}
|
|
2215
|
+
const url2 = await this.runNavigate({
|
|
1910
2216
|
funnelSessionId,
|
|
1911
2217
|
stepId: input.stepId,
|
|
1912
2218
|
session,
|
|
1913
2219
|
input,
|
|
1914
2220
|
currentUrl
|
|
1915
2221
|
});
|
|
1916
|
-
return { url, funnelSessionId };
|
|
2222
|
+
return { url: url2, funnelSessionId };
|
|
1917
2223
|
}
|
|
1918
2224
|
// -------------------------------------------------------------------------
|
|
1919
2225
|
// Internals
|
|
@@ -2022,8 +2328,24 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2022
2328
|
|
|
2023
2329
|
// src/core/modules/rx.ts
|
|
2024
2330
|
var RxModule = class {
|
|
2025
|
-
constructor(http) {
|
|
2331
|
+
constructor(http, storeId) {
|
|
2026
2332
|
this.http = http;
|
|
2333
|
+
this.storeId = storeId;
|
|
2334
|
+
}
|
|
2335
|
+
/**
|
|
2336
|
+
* Activation status of the store: steps, missing items and whether Rx
|
|
2337
|
+
* payments are `setting_up` or `ready`. Storefronts use it to show
|
|
2338
|
+
* "Payments are being set up" instead of letting a checkout fail.
|
|
2339
|
+
*
|
|
2340
|
+
* Read-only / public. Defaults to the client's `storeId`.
|
|
2341
|
+
*/
|
|
2342
|
+
async getActivationStatus(storeId) {
|
|
2343
|
+
const id = storeId ?? this.storeId;
|
|
2344
|
+
if (!id)
|
|
2345
|
+
throw new Error("rx.getActivationStatus: storeId is required");
|
|
2346
|
+
return this.http.get("/api/public/v1/rx/activation-status", {
|
|
2347
|
+
params: { storeId: id }
|
|
2348
|
+
});
|
|
2027
2349
|
}
|
|
2028
2350
|
/**
|
|
2029
2351
|
* Check whether a product requires an Rx case. Storefronts call this
|
|
@@ -2070,6 +2392,96 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2070
2392
|
}
|
|
2071
2393
|
};
|
|
2072
2394
|
|
|
2395
|
+
// src/core/modules/experiments.ts
|
|
2396
|
+
var ExperimentsModule = class {
|
|
2397
|
+
constructor(core, bootstrap) {
|
|
2398
|
+
this.core = core;
|
|
2399
|
+
this.bootstrap = bootstrap;
|
|
2400
|
+
this.runtime = null;
|
|
2401
|
+
this.loading = null;
|
|
2402
|
+
this.settled = false;
|
|
2403
|
+
this.reads = /* @__PURE__ */ new Set();
|
|
2404
|
+
this.subscribers = [];
|
|
2405
|
+
}
|
|
2406
|
+
variant(key) {
|
|
2407
|
+
var _a, _b, _c, _d;
|
|
2408
|
+
return ((_b = (_a = this.bootstrap) == null ? void 0 : _a.experiments[key]) == null ? void 0 : _b.arm) ?? ((_d = (_c = this.bootstrap) == null ? void 0 : _c.flags[key]) == null ? void 0 : _d.variant) ?? null;
|
|
2409
|
+
}
|
|
2410
|
+
start() {
|
|
2411
|
+
if (typeof window === "undefined")
|
|
2412
|
+
return Promise.resolve();
|
|
2413
|
+
this.loading ?? (this.loading = (async () => {
|
|
2414
|
+
try {
|
|
2415
|
+
this.runtime = await this.core();
|
|
2416
|
+
} catch {
|
|
2417
|
+
}
|
|
2418
|
+
this.settled = true;
|
|
2419
|
+
const runtime = this.runtime;
|
|
2420
|
+
for (const key of this.reads) {
|
|
2421
|
+
try {
|
|
2422
|
+
runtime == null ? void 0 : runtime.getVariant(key);
|
|
2423
|
+
} catch {
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
this.reads.clear();
|
|
2427
|
+
for (const { key, cb } of this.subscribers.splice(0)) {
|
|
2428
|
+
try {
|
|
2429
|
+
if (runtime)
|
|
2430
|
+
runtime.onVariant(key, cb);
|
|
2431
|
+
else
|
|
2432
|
+
cb(this.variant(key));
|
|
2433
|
+
} catch {
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
try {
|
|
2437
|
+
await (runtime == null ? void 0 : runtime.ready());
|
|
2438
|
+
} catch {
|
|
2439
|
+
}
|
|
2440
|
+
})());
|
|
2441
|
+
return this.loading;
|
|
2442
|
+
}
|
|
2443
|
+
read(key) {
|
|
2444
|
+
if (!this.settled)
|
|
2445
|
+
this.reads.add(key);
|
|
2446
|
+
void this.start();
|
|
2447
|
+
}
|
|
2448
|
+
getVariant(key) {
|
|
2449
|
+
if (this.runtime)
|
|
2450
|
+
return this.runtime.getVariant(key);
|
|
2451
|
+
this.read(key);
|
|
2452
|
+
return this.variant(key);
|
|
2453
|
+
}
|
|
2454
|
+
getPayload(key) {
|
|
2455
|
+
var _a, _b, _c, _d;
|
|
2456
|
+
if (this.runtime)
|
|
2457
|
+
return this.runtime.getPayload(key);
|
|
2458
|
+
this.read(key);
|
|
2459
|
+
return ((_b = (_a = this.bootstrap) == null ? void 0 : _a.experiments[key]) == null ? void 0 : _b.payload) ?? ((_d = (_c = this.bootstrap) == null ? void 0 : _c.flags[key]) == null ? void 0 : _d.payload) ?? null;
|
|
2460
|
+
}
|
|
2461
|
+
isEnabled(flagKey) {
|
|
2462
|
+
var _a, _b;
|
|
2463
|
+
if (this.runtime)
|
|
2464
|
+
return this.runtime.isEnabled(flagKey);
|
|
2465
|
+
this.read(flagKey);
|
|
2466
|
+
return ((_b = (_a = this.bootstrap) == null ? void 0 : _a.flags[flagKey]) == null ? void 0 : _b.enabled) ?? false;
|
|
2467
|
+
}
|
|
2468
|
+
onVariant(key, cb) {
|
|
2469
|
+
if (this.runtime) {
|
|
2470
|
+
this.runtime.onVariant(key, cb);
|
|
2471
|
+
return;
|
|
2472
|
+
}
|
|
2473
|
+
if (this.settled) {
|
|
2474
|
+
cb(this.variant(key));
|
|
2475
|
+
return;
|
|
2476
|
+
}
|
|
2477
|
+
this.subscribers.push({ key, cb });
|
|
2478
|
+
void this.start();
|
|
2479
|
+
}
|
|
2480
|
+
ready() {
|
|
2481
|
+
return this.start();
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
|
|
2073
2485
|
// src/core/client.ts
|
|
2074
2486
|
var HeadlessClient = class {
|
|
2075
2487
|
constructor(config) {
|
|
@@ -2087,21 +2499,43 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2087
2499
|
apiKey: config.apiKey,
|
|
2088
2500
|
getToken: () => this._sessionToken
|
|
2089
2501
|
});
|
|
2502
|
+
this.track = new TrackModule(baseUrl, this.config.storeId, this.config.funnel ?? "main");
|
|
2503
|
+
this.track.bootstrap = this.config.bootstrap;
|
|
2504
|
+
this.experiments = new ExperimentsModule(() => this.track.core(), this.config.bootstrap);
|
|
2090
2505
|
const setToken = (token) => {
|
|
2091
2506
|
this._sessionToken = token;
|
|
2092
2507
|
};
|
|
2093
|
-
this.checkout = new CheckoutModule(
|
|
2094
|
-
|
|
2508
|
+
this.checkout = new CheckoutModule(
|
|
2509
|
+
this.http,
|
|
2510
|
+
this.config.storeId,
|
|
2511
|
+
setToken,
|
|
2512
|
+
(s) => this.track.noteCheckout({
|
|
2513
|
+
checkoutSessionId: s.id,
|
|
2514
|
+
amount: s.totals.total,
|
|
2515
|
+
currency: s.totals.currency,
|
|
2516
|
+
items: toContents(s.items)
|
|
2517
|
+
})
|
|
2518
|
+
);
|
|
2519
|
+
this.payment = new PaymentModule(
|
|
2520
|
+
this.http,
|
|
2521
|
+
this.config.storeId,
|
|
2522
|
+
environment,
|
|
2523
|
+
this.checkout,
|
|
2524
|
+
(p) => this.track.notePaid(p),
|
|
2525
|
+
(v, d) => this.track.noteSignal("wallet_unavailable", v, d)
|
|
2526
|
+
);
|
|
2095
2527
|
this.offers = new OffersModule(this.http, this.config.storeId, this.payment);
|
|
2096
2528
|
this.customer = new CustomerModule(this.http, this.config.storeId);
|
|
2529
|
+
this.portal = new CustomerPortalModule(this.http, this.config.storeId, setToken);
|
|
2097
2530
|
this.catalog = new CatalogModule(this.http, this.config.storeId);
|
|
2098
2531
|
this.funnel = new FunnelModule(
|
|
2099
2532
|
this.http,
|
|
2100
2533
|
this.config.storeId,
|
|
2101
2534
|
this.checkout,
|
|
2102
|
-
this.config.accountId
|
|
2535
|
+
this.config.accountId,
|
|
2536
|
+
(id) => this.track.noteFunnelSession(id)
|
|
2103
2537
|
);
|
|
2104
|
-
this.rx = new RxModule(this.http);
|
|
2538
|
+
this.rx = new RxModule(this.http, this.config.storeId);
|
|
2105
2539
|
}
|
|
2106
2540
|
/** Manually set the session token (e.g. from URL params on page load). */
|
|
2107
2541
|
setSessionToken(token) {
|
|
@@ -2156,13 +2590,13 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2156
2590
|
params.set("language", opts.language);
|
|
2157
2591
|
if (opts.region)
|
|
2158
2592
|
params.set("region", opts.region);
|
|
2159
|
-
const
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
document.head.appendChild(
|
|
2593
|
+
const script2 = document.createElement("script");
|
|
2594
|
+
script2.src = `https://maps.googleapis.com/maps/api/js?${params}`;
|
|
2595
|
+
script2.async = true;
|
|
2596
|
+
script2.defer = true;
|
|
2597
|
+
script2.onload = () => onScriptReady();
|
|
2598
|
+
script2.onerror = () => reject(new Error("Failed to load Google Maps script"));
|
|
2599
|
+
document.head.appendChild(script2);
|
|
2166
2600
|
});
|
|
2167
2601
|
}
|
|
2168
2602
|
var GoogleAutocompleteCore = class _GoogleAutocompleteCore {
|
|
@@ -2311,10 +2745,10 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2311
2745
|
if (inflight)
|
|
2312
2746
|
return inflight;
|
|
2313
2747
|
inflight = (async () => {
|
|
2314
|
-
const
|
|
2315
|
-
const res = await fetch(
|
|
2748
|
+
const url2 = `${GEODATA_CDN_BASE}/${language}/countries.json`;
|
|
2749
|
+
const res = await fetch(url2);
|
|
2316
2750
|
if (!res.ok)
|
|
2317
|
-
throw new Error(`Geodata fetch failed: ${
|
|
2751
|
+
throw new Error(`Geodata fetch failed: ${url2} (${res.status})`);
|
|
2318
2752
|
const data = await res.json();
|
|
2319
2753
|
countriesCache.set(language, data);
|
|
2320
2754
|
inflightCountries.delete(language);
|
|
@@ -2331,10 +2765,10 @@ var TagadaHeadlessBundle = (() => {
|
|
|
2331
2765
|
if (inflight)
|
|
2332
2766
|
return inflight;
|
|
2333
2767
|
inflight = (async () => {
|
|
2334
|
-
const
|
|
2335
|
-
const res = await fetch(
|
|
2768
|
+
const url2 = `${GEODATA_CDN_BASE}/${language}/regions.json`;
|
|
2769
|
+
const res = await fetch(url2);
|
|
2336
2770
|
if (!res.ok)
|
|
2337
|
-
throw new Error(`Geodata fetch failed: ${
|
|
2771
|
+
throw new Error(`Geodata fetch failed: ${url2} (${res.status})`);
|
|
2338
2772
|
const data = await res.json();
|
|
2339
2773
|
regionsCache.set(language, data);
|
|
2340
2774
|
inflightRegions.delete(language);
|