| | |
| | | register(name, configs = [], version = 1.25) { |
| | | if (!Array.isArray(configs)) configs = [configs]; |
| | | if (configs.length === 0) return; |
| | | |
| | | if (!this.dbConfig.has(name)) { |
| | | this.dbConfig.set(name, { |
| | | dbName: `${jvbBase.base}${name}`, |
| | |
| | | ignore: [], //any filters to ignore when filtering store locally |
| | | required: null, |
| | | |
| | | isAuth: false, |
| | | |
| | | // Cache |
| | | TTL: 3600000, // 1 hour |
| | | useHttpCaching: true, |
| | |
| | | } |
| | | }); |
| | | |
| | | |
| | | // Initialize database asynchronously |
| | | this.initDB(name).catch(error => { |
| | | console.error(`Failed to initialize store "${name}":`, error); |
| | |
| | | const controller = new AbortController(); |
| | | store.currentRequest = controller; |
| | | |
| | | const response = await fetch(url, { |
| | | method: 'GET', |
| | | headers, |
| | | signal: controller.signal |
| | | }); |
| | | let response; |
| | | if (store.isAuth) { |
| | | response = await window.auth.fetch(url, { |
| | | method: 'GET', |
| | | headers, |
| | | signal: controller.signal |
| | | }); |
| | | } else { |
| | | response = await fetch(url, { |
| | | method: 'GET', |
| | | headers, |
| | | signal: controller.signal |
| | | }); |
| | | } |
| | | |
| | | if (!response.ok) { |
| | | // Access the error details from the response body |
| | | const errorBody = await response.text(); |
| | | // Throw a new error with a descriptive message |
| | | throw new Error(`HTTP error! status: ${response.status}, message: ${errorBody}`); |
| | | } |
| | | |
| | | if (response.status === 304) { |
| | | // 304 means "Not Modified" - use cached data if available |
| | |
| | | if (!response.ok) { |
| | | throw new Error(`HTTP ${response.status}: ${response.statusText}`); |
| | | } |
| | | |
| | | const data = await response.json(); |
| | | |
| | | await this.processFetchedData(name, data, cacheKey, response); |
| | |
| | | const isAbortError = error?.name === 'AbortError'; |
| | | |
| | | if (!isAbortError) { |
| | | console.error(`Fetch error for store "${name}":`, error); |
| | | console.error(`Fetch error for store "${name}":`, error.message); |
| | | console.dir(error); |
| | | this.notify(name, 'fetch-error', { error }); |
| | | throw error; |
| | | } |
| | |
| | | if (type === 'object') { |
| | | const processed = {}; |
| | | for (const [key, value] of Object.entries(obj)) { |
| | | if (value === undefined) continue; |
| | | const result = this.processForStorage(value, validate, `${path}.${key}`); |
| | | if (!result.valid) return result; |
| | | // Include null values, skip undefined |
| | |
| | | |
| | | // Handle other filters |
| | | for (const [key, value] of Object.entries(store.filters)) { |
| | | if (key === 'taxonomy') continue; |
| | | if (key === 'taxonomy') { |
| | | if (typeof value === 'string' && !value.includes(',')) { |
| | | filterPredicates.push(item => item.taxonomy === value); |
| | | } |
| | | continue; |
| | | } |
| | | if (store.ignoreFilters.has(key)) { |
| | | continue; |
| | | } |
| | |
| | | } |
| | | |
| | | if (store.lastResponse.has_more === false) { |
| | | // Check if new filters are a subset of what we have |
| | | const isSubsetFilter = Object.entries(updates).every(([key, value]) => { |
| | | if (store.ignoreFilters.has(key)) return true; |
| | | if (key === 'page') return true; // Handle pagination locally |
| | | return true; // We have all data, can filter locally |
| | | }); |
| | | |
| | | if (isSubsetFilter) return false; |
| | | if (this.hasCompleteData(store, store.filters)) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | if ('page' in updates) { |