@shoppexio/storefront 1.0.84 → 1.0.87
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/CHANGELOG.md +11 -0
- package/README.md +2 -0
- package/dist/index.cjs +110 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -4
- package/dist/index.d.ts +16 -4
- package/dist/index.js +110 -63
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1701,7 +1701,14 @@ declare function validateCoupon(code: string, productOrOptions?: string | Coupon
|
|
|
1701
1701
|
* Note: Shoppex has shop-level feedback, not product-level reviews.
|
|
1702
1702
|
*/
|
|
1703
1703
|
|
|
1704
|
-
|
|
1704
|
+
interface ShopReviewsPageOptions {
|
|
1705
|
+
/**
|
|
1706
|
+
* One product's reviews, by the product's public id (the `id` the catalog
|
|
1707
|
+
* carries). The page's `summary` then counts that product's reviews only.
|
|
1708
|
+
*/
|
|
1709
|
+
product?: string | null;
|
|
1710
|
+
}
|
|
1711
|
+
declare function getShopReviewsPage(cursor?: string | null, options?: ShopReviewsPageOptions): Promise<SDKResponse<ShopReviewsPage>>;
|
|
1705
1712
|
declare function getShopReviews(): Promise<SDKResponse<Feedback[]>>;
|
|
1706
1713
|
|
|
1707
1714
|
/**
|
|
@@ -1916,9 +1923,14 @@ declare function trackPageView(cartValue?: number, itemCount?: number): Promise<
|
|
|
1916
1923
|
/**
|
|
1917
1924
|
* Reports a cart change for the live visitor map without counting a page view
|
|
1918
1925
|
* (`event_type: 'presence'`). Use it when the cart changes on a page that was
|
|
1919
|
-
* already counted. A cart state
|
|
1920
|
-
* not sent again, so a cross-tab `storage`
|
|
1921
|
-
* ping.
|
|
1926
|
+
* already counted. A cart state the server already acknowledged, or that a tab
|
|
1927
|
+
* of this shop is sending right now, is not sent again, so a cross-tab `storage`
|
|
1928
|
+
* echo of a change is not a second ping. A failed send leaves nothing behind:
|
|
1929
|
+
* the same state goes out again on the next change or page load.
|
|
1930
|
+
*
|
|
1931
|
+
* The check runs when the change's turn comes, after this tab's earlier sends
|
|
1932
|
+
* settled, never at call time: a revert to the confirmed cart while another
|
|
1933
|
+
* state is on the wire must still go out once that send confirms its state.
|
|
1922
1934
|
*/
|
|
1923
1935
|
declare function trackCartActivity(cartValue: number, itemCount: number): Promise<void>;
|
|
1924
1936
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1701,7 +1701,14 @@ declare function validateCoupon(code: string, productOrOptions?: string | Coupon
|
|
|
1701
1701
|
* Note: Shoppex has shop-level feedback, not product-level reviews.
|
|
1702
1702
|
*/
|
|
1703
1703
|
|
|
1704
|
-
|
|
1704
|
+
interface ShopReviewsPageOptions {
|
|
1705
|
+
/**
|
|
1706
|
+
* One product's reviews, by the product's public id (the `id` the catalog
|
|
1707
|
+
* carries). The page's `summary` then counts that product's reviews only.
|
|
1708
|
+
*/
|
|
1709
|
+
product?: string | null;
|
|
1710
|
+
}
|
|
1711
|
+
declare function getShopReviewsPage(cursor?: string | null, options?: ShopReviewsPageOptions): Promise<SDKResponse<ShopReviewsPage>>;
|
|
1705
1712
|
declare function getShopReviews(): Promise<SDKResponse<Feedback[]>>;
|
|
1706
1713
|
|
|
1707
1714
|
/**
|
|
@@ -1916,9 +1923,14 @@ declare function trackPageView(cartValue?: number, itemCount?: number): Promise<
|
|
|
1916
1923
|
/**
|
|
1917
1924
|
* Reports a cart change for the live visitor map without counting a page view
|
|
1918
1925
|
* (`event_type: 'presence'`). Use it when the cart changes on a page that was
|
|
1919
|
-
* already counted. A cart state
|
|
1920
|
-
* not sent again, so a cross-tab `storage`
|
|
1921
|
-
* ping.
|
|
1926
|
+
* already counted. A cart state the server already acknowledged, or that a tab
|
|
1927
|
+
* of this shop is sending right now, is not sent again, so a cross-tab `storage`
|
|
1928
|
+
* echo of a change is not a second ping. A failed send leaves nothing behind:
|
|
1929
|
+
* the same state goes out again on the next change or page load.
|
|
1930
|
+
*
|
|
1931
|
+
* The check runs when the change's turn comes, after this tab's earlier sends
|
|
1932
|
+
* settled, never at call time: a revert to the confirmed cart while another
|
|
1933
|
+
* state is on the wire must still go out once that send confirms its state.
|
|
1922
1934
|
*/
|
|
1923
1935
|
declare function trackCartActivity(cartValue: number, itemCount: number): Promise<void>;
|
|
1924
1936
|
|
package/dist/index.js
CHANGED
|
@@ -3318,6 +3318,8 @@ function removeItem(key) {
|
|
|
3318
3318
|
// ../sdk/src/core/telemetry.ts
|
|
3319
3319
|
var CONNECTION_ID_STORAGE_PREFIX = "presence_connection_";
|
|
3320
3320
|
var CLIENT_ERROR_DEDUPE_WINDOW_MS = 15e3;
|
|
3321
|
+
var CLIENT_ERROR_TEXT_MAX_LENGTH = 500;
|
|
3322
|
+
var CLIENT_ERROR_URL_MAX_LENGTH = 2e3;
|
|
3321
3323
|
function createPresenceConnectionId() {
|
|
3322
3324
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
3323
3325
|
return crypto.randomUUID();
|
|
@@ -3368,14 +3370,14 @@ async function reportStorefrontClientError(payload) {
|
|
|
3368
3370
|
client_error: {
|
|
3369
3371
|
source: payload.source ?? "sdk",
|
|
3370
3372
|
phase: payload.phase ?? "request",
|
|
3371
|
-
endpoint: payload.endpoint,
|
|
3373
|
+
endpoint: payload.endpoint.slice(0, CLIENT_ERROR_TEXT_MAX_LENGTH),
|
|
3372
3374
|
method: payload.method,
|
|
3373
|
-
message: payload.message,
|
|
3375
|
+
message: payload.message.slice(0, CLIENT_ERROR_TEXT_MAX_LENGTH),
|
|
3374
3376
|
status_code: payload.statusCode,
|
|
3375
3377
|
attempt_count: payload.attemptCount,
|
|
3376
3378
|
response_received: payload.responseReceived ?? false,
|
|
3377
|
-
page_url: payload.pageUrl ?? window.location.href,
|
|
3378
|
-
request_url: payload.requestUrl,
|
|
3379
|
+
page_url: (payload.pageUrl ?? window.location.href).slice(0, CLIENT_ERROR_URL_MAX_LENGTH),
|
|
3380
|
+
request_url: payload.requestUrl?.slice(0, CLIENT_ERROR_URL_MAX_LENGTH),
|
|
3379
3381
|
online: payload.online ?? (typeof navigator !== "undefined" ? navigator.onLine : void 0),
|
|
3380
3382
|
visibility_state: payload.visibilityState ?? (typeof document !== "undefined" ? document.visibilityState : void 0)
|
|
3381
3383
|
}
|
|
@@ -5370,13 +5372,17 @@ function normalizeFeedback(raw, index) {
|
|
|
5370
5372
|
created_at
|
|
5371
5373
|
};
|
|
5372
5374
|
}
|
|
5373
|
-
async function getShopReviewsPage(cursor) {
|
|
5375
|
+
async function getShopReviewsPage(cursor, options = {}) {
|
|
5374
5376
|
const config = getConfig();
|
|
5375
5377
|
const query = new URLSearchParams();
|
|
5376
5378
|
query.set("limit", String(REVIEWS_PAGE_LIMIT));
|
|
5377
5379
|
if (typeof cursor === "string" && cursor.trim().length > 0) {
|
|
5378
5380
|
query.set("cursor", cursor);
|
|
5379
5381
|
}
|
|
5382
|
+
const product = typeof options.product === "string" ? options.product.trim() : "";
|
|
5383
|
+
if (product) {
|
|
5384
|
+
query.set("product", product);
|
|
5385
|
+
}
|
|
5380
5386
|
const querySuffix = `?${query.toString()}`;
|
|
5381
5387
|
const response = await get(
|
|
5382
5388
|
`${buildEndpoint("/v1/storefront/feedback/shop/:storeSlug", {
|
|
@@ -5384,7 +5390,7 @@ async function getShopReviewsPage(cursor) {
|
|
|
5384
5390
|
})}${querySuffix}`,
|
|
5385
5391
|
{
|
|
5386
5392
|
cache: {
|
|
5387
|
-
key: `reviews:${config.storeSlug}:${cursor ?? "start"}:${REVIEWS_PAGE_LIMIT}`,
|
|
5393
|
+
key: `reviews:${config.storeSlug}:${product || "all"}:${cursor ?? "start"}:${REVIEWS_PAGE_LIMIT}`,
|
|
5388
5394
|
ttl: REVIEWS_CACHE_TTL,
|
|
5389
5395
|
staleWhileRevalidate: true
|
|
5390
5396
|
}
|
|
@@ -5399,10 +5405,7 @@ async function getShopReviewsPage(cursor) {
|
|
|
5399
5405
|
}
|
|
5400
5406
|
};
|
|
5401
5407
|
}
|
|
5402
|
-
return
|
|
5403
|
-
success: false,
|
|
5404
|
-
message: response.message
|
|
5405
|
-
};
|
|
5408
|
+
return forwardFailure(response);
|
|
5406
5409
|
}
|
|
5407
5410
|
async function getShopReviews() {
|
|
5408
5411
|
const allFeedback = [];
|
|
@@ -5872,10 +5875,7 @@ async function getPages() {
|
|
|
5872
5875
|
data: response.data.pages
|
|
5873
5876
|
};
|
|
5874
5877
|
}
|
|
5875
|
-
return
|
|
5876
|
-
success: false,
|
|
5877
|
-
message: response.message
|
|
5878
|
-
};
|
|
5878
|
+
return forwardFailure(response);
|
|
5879
5879
|
}
|
|
5880
5880
|
async function getPage(slug) {
|
|
5881
5881
|
const config = getConfig();
|
|
@@ -5898,10 +5898,7 @@ async function getPage(slug) {
|
|
|
5898
5898
|
data: response.data.page
|
|
5899
5899
|
};
|
|
5900
5900
|
}
|
|
5901
|
-
return
|
|
5902
|
-
success: false,
|
|
5903
|
-
message: response.message
|
|
5904
|
-
};
|
|
5901
|
+
return forwardFailure(response);
|
|
5905
5902
|
}
|
|
5906
5903
|
|
|
5907
5904
|
// ../sdk/src/modules/navigation.ts
|
|
@@ -6083,72 +6080,122 @@ function isPlatformPageTrackerActive() {
|
|
|
6083
6080
|
}
|
|
6084
6081
|
|
|
6085
6082
|
// ../sdk/src/modules/analytics.ts
|
|
6086
|
-
var
|
|
6087
|
-
|
|
6088
|
-
|
|
6083
|
+
var CONFIRMED_CART_STORAGE_PREFIX = "reported_cart_";
|
|
6084
|
+
var IN_FLIGHT_CART_STORAGE_PREFIX = "reporting_cart_";
|
|
6085
|
+
var CART_CLAIM_TTL_MS = 1e4;
|
|
6086
|
+
function confirmedCartKey(storeSlug) {
|
|
6087
|
+
return `${CONFIRMED_CART_STORAGE_PREFIX}${storeSlug}`;
|
|
6088
|
+
}
|
|
6089
|
+
function inFlightCartKey(storeSlug) {
|
|
6090
|
+
return `${IN_FLIGHT_CART_STORAGE_PREFIX}${storeSlug}`;
|
|
6089
6091
|
}
|
|
6090
6092
|
function cartSnapshot(cartValue, itemCount) {
|
|
6091
6093
|
return `${cartValue ?? ""}|${itemCount ?? ""}`;
|
|
6092
6094
|
}
|
|
6093
|
-
function
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
if (!isInitialized()) return;
|
|
6098
|
-
if (typeof document === "undefined") return;
|
|
6099
|
-
const carriesCart = cartValue !== void 0 || itemCount !== void 0;
|
|
6100
|
-
if (isPlatformPageTrackerActive()) {
|
|
6101
|
-
if (carriesCart) await sendCartActivity(cartValue ?? 0, itemCount ?? 0);
|
|
6102
|
-
return;
|
|
6095
|
+
function readInFlightCart(storeSlug) {
|
|
6096
|
+
const claim = getItem(inFlightCartKey(storeSlug));
|
|
6097
|
+
if (!claim || typeof claim.snapshot !== "string" || typeof claim.token !== "string" || typeof claim.at !== "number") {
|
|
6098
|
+
return null;
|
|
6103
6099
|
}
|
|
6100
|
+
return claim;
|
|
6101
|
+
}
|
|
6102
|
+
function isCartReportedOrInFlight(storeSlug, snapshot) {
|
|
6103
|
+
if (getItem(confirmedCartKey(storeSlug)) === snapshot) return true;
|
|
6104
|
+
const claim = readInFlightCart(storeSlug);
|
|
6105
|
+
return claim !== null && claim.snapshot === snapshot && Date.now() - claim.at < CART_CLAIM_TTL_MS;
|
|
6106
|
+
}
|
|
6107
|
+
function createClaimToken() {
|
|
6108
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
|
|
6109
|
+
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
|
|
6110
|
+
}
|
|
6111
|
+
function claimCartReport(storeSlug, cartValue, itemCount) {
|
|
6112
|
+
const snapshot = cartSnapshot(cartValue, itemCount);
|
|
6113
|
+
const token = createClaimToken();
|
|
6114
|
+
setItem(inFlightCartKey(storeSlug), { snapshot, token, at: Date.now() });
|
|
6115
|
+
return (delivered) => {
|
|
6116
|
+
if (readInFlightCart(storeSlug)?.token !== token) return;
|
|
6117
|
+
if (delivered) setItem(confirmedCartKey(storeSlug), snapshot);
|
|
6118
|
+
removeItem(inFlightCartKey(storeSlug));
|
|
6119
|
+
};
|
|
6120
|
+
}
|
|
6121
|
+
var cartSendTail = Promise.resolve();
|
|
6122
|
+
var latestCartRequest = 0;
|
|
6123
|
+
function enqueueCartSend(send) {
|
|
6124
|
+
const request2 = ++latestCartRequest;
|
|
6125
|
+
const run = () => send(() => request2 === latestCartRequest);
|
|
6126
|
+
cartSendTail = cartSendTail.then(run, run);
|
|
6127
|
+
return cartSendTail;
|
|
6128
|
+
}
|
|
6129
|
+
async function postPing(body) {
|
|
6104
6130
|
const config = getConfig();
|
|
6105
|
-
const
|
|
6106
|
-
|
|
6131
|
+
const controller = typeof AbortController === "undefined" ? void 0 : new AbortController();
|
|
6132
|
+
let timer;
|
|
6133
|
+
const timedOut = new Promise((resolve) => {
|
|
6134
|
+
timer = setTimeout(() => {
|
|
6135
|
+
controller?.abort();
|
|
6136
|
+
resolve(false);
|
|
6137
|
+
}, CART_CLAIM_TTL_MS);
|
|
6138
|
+
});
|
|
6107
6139
|
try {
|
|
6108
6140
|
const endpoint = buildEndpoint("/v1/storefront/shops/:storeSlug/ping", {
|
|
6109
6141
|
storeSlug: config.storeSlug
|
|
6110
6142
|
});
|
|
6111
|
-
|
|
6143
|
+
const delivered = fetch(`${config.apiBaseUrl}${endpoint}`, {
|
|
6112
6144
|
method: "POST",
|
|
6113
6145
|
headers: { "Content-Type": "application/json" },
|
|
6114
|
-
body: JSON.stringify(
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
connection_id: connectionId ?? void 0,
|
|
6119
|
-
path: resolveStorefrontPagePath(),
|
|
6120
|
-
utm: resolveUtmParameters(config.storeSlug)
|
|
6121
|
-
})
|
|
6122
|
-
});
|
|
6146
|
+
body: JSON.stringify(body),
|
|
6147
|
+
signal: controller?.signal
|
|
6148
|
+
}).then((response) => response.ok);
|
|
6149
|
+
return await Promise.race([delivered, timedOut]);
|
|
6123
6150
|
} catch {
|
|
6151
|
+
return false;
|
|
6152
|
+
} finally {
|
|
6153
|
+
clearTimeout(timer);
|
|
6124
6154
|
}
|
|
6125
6155
|
}
|
|
6156
|
+
async function trackPageView(cartValue, itemCount) {
|
|
6157
|
+
if (!isInitialized()) return;
|
|
6158
|
+
if (typeof document === "undefined") return;
|
|
6159
|
+
const carriesCart = cartValue !== void 0 || itemCount !== void 0;
|
|
6160
|
+
if (isPlatformPageTrackerActive()) {
|
|
6161
|
+
if (carriesCart) await enqueueCartSend(() => sendCartActivity(cartValue, itemCount));
|
|
6162
|
+
return;
|
|
6163
|
+
}
|
|
6164
|
+
const config = getConfig();
|
|
6165
|
+
const sendView = async () => {
|
|
6166
|
+
const settle = carriesCart ? claimCartReport(config.storeSlug, cartValue, itemCount) : void 0;
|
|
6167
|
+
const delivered = await postPing({
|
|
6168
|
+
referer: document.referrer || void 0,
|
|
6169
|
+
cart_value: cartValue,
|
|
6170
|
+
item_count: itemCount,
|
|
6171
|
+
connection_id: getStorefrontConnectionId(config.storeSlug) ?? void 0,
|
|
6172
|
+
path: resolveStorefrontPagePath(),
|
|
6173
|
+
utm: resolveUtmParameters(config.storeSlug)
|
|
6174
|
+
});
|
|
6175
|
+
settle?.(delivered);
|
|
6176
|
+
};
|
|
6177
|
+
await (carriesCart ? enqueueCartSend(sendView) : sendView());
|
|
6178
|
+
}
|
|
6126
6179
|
async function trackCartActivity(cartValue, itemCount) {
|
|
6127
6180
|
if (!isInitialized()) return;
|
|
6128
6181
|
if (typeof document === "undefined") return;
|
|
6129
|
-
|
|
6130
|
-
await
|
|
6182
|
+
const snapshot = cartSnapshot(cartValue, itemCount);
|
|
6183
|
+
await enqueueCartSend(async (isLatest) => {
|
|
6184
|
+
if (!isLatest() || isCartReportedOrInFlight(getConfig().storeSlug, snapshot)) return;
|
|
6185
|
+
await sendCartActivity(cartValue, itemCount);
|
|
6186
|
+
});
|
|
6131
6187
|
}
|
|
6132
6188
|
async function sendCartActivity(cartValue, itemCount) {
|
|
6133
6189
|
const config = getConfig();
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
event_type: "presence",
|
|
6144
|
-
cart_value: cartValue,
|
|
6145
|
-
item_count: itemCount,
|
|
6146
|
-
connection_id: getStorefrontConnectionId(config.storeSlug) ?? void 0,
|
|
6147
|
-
path: resolveStorefrontPagePath()
|
|
6148
|
-
})
|
|
6149
|
-
});
|
|
6150
|
-
} catch {
|
|
6151
|
-
}
|
|
6190
|
+
const settle = claimCartReport(config.storeSlug, cartValue, itemCount);
|
|
6191
|
+
const delivered = await postPing({
|
|
6192
|
+
event_type: "presence",
|
|
6193
|
+
cart_value: cartValue,
|
|
6194
|
+
item_count: itemCount,
|
|
6195
|
+
connection_id: getStorefrontConnectionId(config.storeSlug) ?? void 0,
|
|
6196
|
+
path: resolveStorefrontPagePath()
|
|
6197
|
+
});
|
|
6198
|
+
settle(delivered);
|
|
6152
6199
|
}
|
|
6153
6200
|
|
|
6154
6201
|
// ../sdk/src/modules/presence.ts
|