// resources/js/utils/RequestData.js import { useHashKeyCache } from '../composables/useHashKeyCache.js'; /** * Modern implementation of the RequestData pattern. * Supports method chaining and integration with HashKeyCache. */ export class RequestData { constructor(withHashCheck = false) { this._url = ''; this._type = 'GET'; this._data = null; this._success = null; this._error = null; this._fromVarCache = false; this._withHashCheck = withHashCheck; this._hashCache = useHashKeyCache(); } /** Set the request URL */ url(u) { this._url = u; return this; } /** Set the HTTP method (GET, POST, etc.) */ type(t) { this._type = t.toUpperCase(); return this; } /** Set the request payload */ data(d) { this._data = d; return this; } /** Set the success callback */ success(callback) { this._success = callback; return this; } /** Set the error callback */ error(callback) { this._error = callback; return this; } /** Enable or disable cache-first behavior */ fromVarCache(bool) { this._fromVarCache = bool; return this; } /** Execute the request */ async go() { if (!this._url) { console.error('[RequestData] URL is missing'); return; } // 1. Check HashKey/Payload in URL first if applicable const urlMatch = this._hashCache.parseHashUrl(this._url); if (urlMatch.type !== 'none' && urlMatch.data) { if (this._success) this._success(urlMatch.data, urlMatch.value); return; } // 2. Check Var Cache (in-memory) if requested if (this._fromVarCache) { const cachedData = this._hashCache.getHashData(this._url); if (cachedData) { if (this._success) this._success(cachedData); // Revalidate in background (Stale-While-Revalidate pattern) this._fetchFromServer(true); return; } } // 3. Perform network request return this._fetchFromServer(); } /** Internal fetch implementation */ async _fetchFromServer(background = false) { try { const options = { method: this._type, headers: { 'Accept': 'application/json', } }; if (this._data && (this._type === 'POST' || this._type === 'PUT')) { options.headers['Content-Type'] = 'application/json'; options.body = JSON.stringify(this._data); } const response = await fetch(this._url, options); if (!response.ok) throw new Error(`HTTP ${response.status}`); const result = await response.json(); // Update cache if (this._fromVarCache) { this._hashCache.setHashData(this._url, result); } // If background revalidation found non-identical data, you might want to call success again // or use Pinia to update the UI reactively. if (this._success) { // For simplicity, we call success again if it's a background fetch // but usually you want a way to avoid jitter if data is the same. this._success(result); } return result; } catch (err) { if (!background && this._error) { this._error(err); } if (background) { console.warn('[RequestData] Background revalidation failed:', err); } } } } /** Wrapper function for easier instantiation */ export function request(withHashCheck = false) { return new RequestData(withHashCheck); }