← back to Dw Theme Boost Fix
verify/interceptor.js
104 lines
(function () {
'use strict';
if (window.__dwBoostInfinite) return;
window.__dwBoostInfinite = true;
var TARGET = 'infinite_scroll';
// Verified production Boost SD endpoints for this shop (2026-07-13).
var PROD_API = {
filterUrl: 'https://services.mybcapps.com/bc-sf-filter/filter',
searchUrl: 'https://services.mybcapps.com/bc-sf-filter/search',
suggestionUrl: 'https://services.mybcapps.com/bc-sf-filter/search/suggest',
productsUrl: 'https://services.mybcapps.com/bc-sf-filter/search/products',
recommendUrl: 'https://services.mybcapps.com/discovery/recommend',
analyticsUrl: 'https://lambda.mybcapps.com/e',
cdn: 'https://boost-cdn-prod.bc-solutions.net'
};
// Rewrite ONLY staging bc-solutions endpoints to production. Anything that
// already points at a non-staging host is left untouched, so an upstream
// Boost fix (or an intentional custom endpoint) is never clobbered.
function isStaging(v) {
return typeof v === 'string' &&
(v.indexOf('staging.bc-solutions.net') !== -1 ||
v.indexOf('boost-cdn-staging') !== -1);
}
function patchApi(api) {
if (!api || typeof api !== 'object') return;
for (var k in PROD_API) {
if (!Object.prototype.hasOwnProperty.call(PROD_API, k)) continue;
try {
if (isStaging(api[k])) api[k] = PROD_API[k];
} catch (e) {}
}
}
// Recursively rewrite any "paginationType" key to infinite_scroll, plus the
// common Boost shapes (generalSettings + additionalElements.pagination).
// `seen` guards against cyclic / shared references so a self-referential
// Boost config can't loop or get re-walked needlessly.
function patchObj(o, depth, seen) {
if (!o || typeof o !== 'object' || depth > 6) return;
if (seen.indexOf(o) !== -1) return;
seen.push(o);
try {
if (Object.prototype.hasOwnProperty.call(o, 'paginationType') &&
typeof o.paginationType === 'string') {
o.paginationType = TARGET;
}
// Boost sometimes nests under .pagination: { paginationType, ... }
if (o.pagination && typeof o.pagination === 'object' &&
typeof o.pagination.paginationType === 'string') {
o.pagination.paginationType = TARGET;
}
} catch (e) {}
for (var k in o) {
if (!Object.prototype.hasOwnProperty.call(o, k)) continue;
var v = o[k];
if (v && typeof v === 'object') patchObj(v, depth + 1, seen);
}
}
function patchConfig(cfg) {
if (!cfg || typeof cfg !== 'object') return cfg;
try {
// One shared `seen` set across all walks keeps total work O(n) and
// cycle-safe — known surfaces get a full-depth targeted walk, then the
// catch-all root walk skips anything already visited (schema-drift safe).
var seen = [];
patchApi(cfg.api); // endpoint repoint — staging → production (2026-07-13)
if (cfg.generalSettings) patchObj(cfg.generalSettings, 0, seen);
if (cfg.additionalElements) patchObj(cfg.additionalElements, 0, seen);
patchObj(cfg, 0, seen);
} catch (e) {}
return cfg;
}
// (1) defineProperty setter — intercept Boost's assignment.
var _cfg = window.boostSDAppConfig;
try {
Object.defineProperty(window, 'boostSDAppConfig', {
configurable: true,
enumerable: true,
get: function () { return _cfg; },
set: function (val) { _cfg = patchConfig(val); }
});
} catch (e) {
// If defineProperty fails (already non-configurable), fall through to poll.
}
// (2) Patch immediately if it already exists.
if (_cfg) patchConfig(_cfg);
// (3) Short poll — re-apply in case Boost replaces / re-inits the object,
// and re-patch after a few frames so the value is correct at bundle init.
var ticks = 0;
var iv = setInterval(function () {
ticks++;
try { if (window.boostSDAppConfig) patchConfig(window.boostSDAppConfig); } catch (e) {}
if (ticks > 80) clearInterval(iv); // ~8s @ 100ms, well past Boost init
}, 100);
})();