1(function() { 2 if (typeof window === 'undefined' || typeof window.fetch !== 'function') return; 3 if (window.__ashlerDeploymentAwareFetchInstalled) return; 4 5 var deploymentId = resolveDeploymentId(); 6 window.__ashlerDeploymentAwareFetchInstalled = true; 7 8 var originalFetch = window.fetch.bind(window); 9 var deploymentHeaderName = 'x-ashler-deployment-id'; 10 var nextDeploymentHeaderName = 'x-deployment-id'; 11 var activeDeploymentHeaderName = 'x-ashler-active-deployment-id'; 12 var beforeHardRefreshEventName = 'ashler:before-deployment-hard-refresh'; 13 var hardRefreshReadyEventName = 'ashler:deployment-hard-refresh-ready'; 14 var hardRefreshFallbackParamName = '__ashler_hard_refresh'; 15 var stableDeploymentId = 'stable'; 16 var reloadReasonStorageKey = 'ashler:page-reload'; 17 var resumeDeploymentCheckUrl = '/api/readyz'; 18 var resumeDeploymentCheckInFlight = false; 19 var resumeDeploymentCheckMinIntervalMs = 60000; 20 var lastResumeDeploymentCheckAt = 0; 21 var refreshScheduled = false; 22 var pendingRefresh = null; 23 24 function deploymentIdFromStaticAsset(rawUrl) { 25 if (!rawUrl) return ''; 26 try { 27 var target = new URL(String(rawUrl), window.location.href); 28 if (target.origin !== window.location.origin) return ''; 29 if (target.pathname.indexOf('/_next/static/') !== 0) return ''; 30 return target.searchParams.get('dpl') || ''; 31 } catch (_) { 32 return ''; 33 } 34 } 35 36 function resolveDeploymentId() { 37 var documentDeploymentId = 38 (document.documentElement && document.documentElement.getAttribute('data-dpl-id')) || ''; 39 if (documentDeploymentId) return documentDeploymentId; 40 41 var scripts = typeof document.querySelectorAll === 'function' 42 ? document.querySelectorAll('script[src]') 43 : []; 44 for (var index = 0; index < scripts.length; index += 1) { 45 var scriptDeploymentId = deploymentIdFromStaticAsset(scripts[index].src); 46 if (scriptDeploymentId) return scriptDeploymentId; 47 } 48 return ''; 49 } 50 51 function isSameOriginRequest(rawUrl) { 52 if (!rawUrl) return false; 53 try { 54 var target = new URL(String(rawUrl), window.location.href); 55 return target.origin === window.location.origin; 56 } catch (_) { 57 return false; 58 } 59 } 60 61 function isSameOriginApiRequest(rawUrl) { 62 if (!rawUrl) return false; 63 try { 64 var target = new URL(String(rawUrl), window.location.href); 65 return target.origin === window.location.origin 66 && (target.pathname === '/api' || target.pathname.indexOf('/api/') === 0); 67 } catch (_) { 68 return false; 69 } 70 } 71 72 function requestUrl(input) { 73 if (typeof input === 'string') return input; 74 if (typeof URL !== 'undefined' && input instanceof URL) return input.href; 75 if (input && typeof input === 'object' && 'url' in input) return input.url; 76 return ''; 77 } 78 79 function requestMethod(input, init) { 80 if (init && init.method) return String(init.method).toUpperCase(); 81 if (typeof Request !== 'undefined' && input instanceof Request && input.method) { 82 return String(input.method).toUpperCase(); 83 } 84 return 'GET'; 85 } 86 87 function isSafeMethod(method) { 88 return method === 'GET' || method === 'HEAD' || method === 'OPTIONS'; 89 } 90 91 function collectHeaders(input, init) { 92 var isRequest = typeof Request !== 'undefined' && input instanceof Request; 93 var headers = new Headers(isRequest ? input.headers : undefined); 94 95 if (init && init.headers) { 96 new Headers(init.headers).forEach(function(value, key) { 97 headers.set(key, value); 98 }); 99 } 100 101 return headers; 102 } 103 104 function hasDeploymentPin(headers) { 105 return headers.has(nextDeploymentHeaderName) || headers.has(deploymentHeaderName); 106 } 107 108 function mergeHeaders(input, init) { 109 var headers = collectHeaders(input, init); 110 111 if (!hasDeploymentPin(headers)) { 112 headers.set(deploymentHeaderName, deploymentId); 113 } 114 115 return headers; 116 } 117 118 function rememberPendingRefresh(request) { 119 if (!pendingRefresh || request.reason === 'pinned-503') { 120 pendingRefresh = request; 121 } 122 } 123 124 function hasHardRefreshFallbackMarker(marker) { 125 try { 126 var currentUrl = new URL(window.location.href); 127 return currentUrl.searchParams.get(hardRefreshFallbackParamName) === marker; 128 } catch (_) { 129 return false;
130 } 131 } 132 133 function hardRefreshFallbackUrl(marker) { 134 try { 135 var refreshUrl = new URL(window.location.href); 136 refreshUrl.searchParams.set(hardRefreshFallbackParamName, marker); 137 return refreshUrl.href; 138 } catch (_) { 139 return ''; 140 } 141 } 142 143 function rememberReloadReason(reason) { 144 try { 145 window.sessionStorage.setItem(reloadReasonStorageKey, JSON.stringify({ reason: reason, at: Date.now() })); 146 } catch (_) { 147 // Storage may be disabled; never block the refresh. 148 } 149 } 150 151 function hardRefreshForDeploymentSkew(reason, activeDeploymentId) { 152 if (refreshScheduled) return; 153 154 var refreshRequest = { 155 reason: reason, 156 deploymentId: deploymentId, 157 activeDeploymentId: activeDeploymentId || '', 158 }; 159 var refreshEvent = new CustomEvent(beforeHardRefreshEventName, { 160 cancelable: true, 161 detail: refreshRequest, 162 }); 163 if (!window.dispatchEvent(refreshEvent)) { 164 rememberPendingRefresh(refreshRequest); 165 return; 166 } 167 168 pendingRefresh = null; 169 170 var refreshKey = 'ashler:deployment-hard-refresh:' + deploymentId + ':' + reason; 171 var refreshFallbackMarker = deploymentId + ':' + reason; 172 if (hasHardRefreshFallbackMarker(refreshFallbackMarker)) return; 173 174 var useUrlFallback = true; 175 try { 176 var refreshStorage = window.sessionStorage; 177 if (refreshStorage && refreshStorage.getItem(refreshKey) === '1') { 178 return; 179 } 180 if (refreshStorage) { 181 refreshStorage.setItem(refreshKey, '1'); 182 useUrlFallback = false; 183 } 184 } catch (_) { 185 useUrlFallback = true; 186 } 187 188 refreshScheduled = true; 189 window.setTimeout(function() { 190 if (useUrlFallback) { 191 var fallbackUrl = hardRefreshFallbackUrl(refreshFallbackMarker); 192 if (fallbackUrl && typeof window.location.replace === 'function') { 193 rememberReloadReason(reason); 194 window.location.replace(fallbackUrl); 195 return; 196 } 197 } 198 rememberReloadReason(reason); 199 window.location.reload(); 200 }, 0); 201 } 202 203 window.addEventListener(hardRefreshReadyEventName, function() { 204 if (!pendingRefresh) return; 205 hardRefreshForDeploymentSkew( 206 pendingRefresh.reason, 207 pendingRefresh.activeDeploymentId, 208 ); 209 }); 210 211 function inspectResponseForDeploymentSkew(response, requestHadDeploymentPin) { 212 if (!response || !response.headers) return; 213 214 var activeDeploymentId = response.headers.get(activeDeploymentHeaderName); 215 if (activeDeploymentId && activeDeploymentId !== deploymentId) { 216 hardRefreshForDeploymentSkew('active-mismatch', activeDeploymentId); 217 return; 218 } 219 220 if (requestHadDeploymentPin && response.status === 503) { 221 hardRefreshForDeploymentSkew('pinned-503', ''); 222 } 223 } 224 225 function clearResumeDeploymentCheck() { 226 resumeDeploymentCheckInFlight = false; 227 } 228 229 function checkActiveDeploymentOnResume() { 230 if (!deploymentId || refreshScheduled || resumeDeploymentCheckInFlight) return; 231 var now = Date.now(); 232 if (lastResumeDeploymentCheckAt && now - lastResumeDeploymentCheckAt < resumeDeploymentCheckMinIntervalMs) return; 233 lastResumeDeploymentCheckAt = now; 234 resumeDeploymentCheckInFlight = true; 235 var headers = new Headers(); 236 headers.set(deploymentHeaderName, stableDeploymentId); 237 originalFetch(resumeDeploymentCheckUrl, { 238 method: 'GET', 239 headers: headers, 240 cache: 'no-store', 241 credentials: 'same-origin', 242 }).then(function(response) { 243 inspectResponseForDeploymentSkew(response, false); 244 }).then(clearResumeDeploymentCheck, clearResumeDeploymentCheck); 245 } 246 247 if (typeof document.addEventListener === 'function') { 248 document.addEventListener('visibilitychange', function() { 249 if (document.visibilityState === 'visible') checkActiveDeploymentOnResume(); 250 }); 251 } 252 253 window.addEventListener('pageshow', function(event) { 254 if (event && event.persisted) checkActiveDeploymentOnResume(); 255 }); 256 257 function isDeploymentChunkScript(target) { 258 if (!target || String(target.tagName || '').toUpperCase() !== 'SCRIPT') return false;
259 260 var rawSrc = target.src || ''; 261 if (!rawSrc) return false; 262 263 try { 264 var targetUrl = new URL(rawSrc, window.location.href); 265 var targetDeploymentId = deploymentIdFromStaticAsset(targetUrl.href); 266 if (!deploymentId && targetDeploymentId) deploymentId = targetDeploymentId; 267 return targetUrl.origin === window.location.origin 268 && targetUrl.pathname.indexOf('/_next/static/chunks/') === 0 269 && !!targetDeploymentId 270 && targetDeploymentId === deploymentId; 271 } catch (_) { 272 return false; 273 } 274 } 275 276 window.addEventListener('error', function(event) { 277 if (!isDeploymentChunkScript(event && event.target)) return; 278 hardRefreshForDeploymentSkew('chunk-load-error', ''); 279 }, true); 280 281 window.fetch = function(input, init) { 282 var rawUrl = requestUrl(input); 283 if (!deploymentId) deploymentId = resolveDeploymentId(); 284 if (!deploymentId || !isSameOriginRequest(rawUrl)) { 285 return originalFetch(input, init); 286 } 287 288 var method = requestMethod(input, init); 289 var existingHeaders = collectHeaders(input, init); 290 var shouldPinApiRequest = isSameOriginApiRequest(rawUrl) 291 && isSafeMethod(method) 292 && !hasDeploymentPin(existingHeaders); 293 var requestHadDeploymentPin = hasDeploymentPin(existingHeaders) || shouldPinApiRequest; 294 var fetchPromise; 295 296 if (shouldPinApiRequest) { 297 var headers = mergeHeaders(input, init); 298 299 if (typeof Request !== 'undefined' && input instanceof Request) { 300 fetchPromise = originalFetch(new Request(input, Object.assign({}, init || {}, { headers: headers }))); 301 } else { 302 fetchPromise = originalFetch(input, Object.assign({}, init || {}, { headers: headers })); 303 } 304 } else { 305 fetchPromise = originalFetch(input, init); 306 } 307 308 return fetchPromise.then(function(response) { 309 inspectResponseForDeploymentSkew(response, requestHadDeploymentPin); 310 return response; 311 }); 312 }; 313})();
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.