1/* Share only overlapping cookie-authenticated points GETs; never retain answers. */ 2(function (window, document) { 3 'use strict'; 4 if (window.sstPointsRequests) return; 5 var generation = 0; 6 var pending = new Map(); 7 var listeners = []; 8 9 function staleError() { 10 var error = new Error('Points context changed'); 11 error.code = 'sst_points_stale'; 12 return error; 13 } 14 15 function request(endpoint, options) { 16 options = options || {}; 17 var method = String(options.method || 'GET').toUpperCase(); 18 var credentials = options.credentials || 'same-origin'; 19 var url; 20 try { url = new URL(endpoint, document.baseURI); } catch (error) { return Promise.reject(error); } 21 if (method !== 'GET' || url.origin !== window.location.origin) { 22 return Promise.reject(new Error('Points provider requires a same-origin GET')); 23 } 24 url.hash = ''; 25 var started = generation; 26 var key = JSON.stringify([url.href, method, credentials, started]); 27 if (pending.has(key)) return pending.get(key); 28 var work = Promise.resolve().then(function () { 29 if (started !== generation) throw staleError(); 30 return window.fetch(url.href, { 31 method: method, 32 credentials: credentials, 33 headers: { Accept: 'application/json' } 34 }); 35 }).then(function (response) { 36 if (!response.ok) throw new Error('sst-points/v1/me failed'); 37 return response.json(); 38 }).then(function (payload) { 39 if (started !== generation) throw staleError(); 40 return payload; 41 }); 42 var shared = work.then(function (payload) { 43 if (pending.get(key) === shared) pending.delete(key); 44 return payload; 45 }, function (error) { 46 if (pending.get(key) === shared) pending.delete(key); 47 throw error; 48 }); 49 pending.set(key, shared); 50 return shared; 51 } 52
53 function invalidate(reason) { 54 generation++; 55 pending.clear(); 56 // Existing fetches finish independently. A single UI must not abort another. 57 listeners.slice().forEach(function (listener) { 58 try { listener(reason || 'auth'); } catch (_) {} 59 }); 60 } 61 62 window.sstPointsRequests = { 63 request: request, 64 generation: function () { return generation; }, 65 invalidate: invalidate, 66 onInvalidate: function (listener) { 67 listeners.push(listener); 68 return function () { listeners = listeners.filter(function (item) { return item !== listener; }); }; 69 } 70 }; 71 72 // Explicit integration contract for same-document auth/points mutations. 73 document.addEventListener('sst:auth-changed', function () { invalidate('auth'); }); 74 document.addEventListener('sst:points-changed', function () { invalidate('points'); }); 75 // Cart totals/redemption toggles change checkout session state, not this 76 // endpoint's earned balance/rank. Do not add GETs to those refresh cycles. 77})(window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.