From ab3aa52e078f3dfcda3705c7a4d40d4db685761c Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 29 Jan 2026 11:51:12 -0500 Subject: [PATCH] A working Data Store element/component again!!! Saving! --- src/lib/ae_core/core__data_store.ts | 66 +++---- ...ha.svelte => element_data_store_v3.svelte} | 169 +++++++++++------- src/routes/testing/data_store_v3/+page.svelte | 48 ++--- 3 files changed, 161 insertions(+), 122 deletions(-) rename src/lib/elements/{element_data_store_v3_alpha.svelte => element_data_store_v3.svelte} (70%) diff --git a/src/lib/ae_core/core__data_store.ts b/src/lib/ae_core/core__data_store.ts index 5eb5ba56..fc7b8cd2 100644 --- a/src/lib/ae_core/core__data_store.ts +++ b/src/lib/ae_core/core__data_store.ts @@ -4,12 +4,12 @@ import { api } from '$lib/api/api'; import type { ae_DataStore } from '$lib/types/ae_types'; /** - * Fetches a data_store object by its unique code. + * Fetches a data_store object by its unique code (V3). * * @param api_cfg - The API configuration object. * @param code - The code of the data store to fetch. * @param data_type - The expected data type ('text', 'json', 'html', 'md', 'sql'). - * @param save_idb - Whether to save the fetched data to localStorage. + * @param save_idb - Whether to save the fetched data to IndexedDB (Dexie). * @param timeout - The request timeout in milliseconds. * @param log_lvl - The logging level. * @returns The data from the data store (e.g., text content or JSON object). @@ -34,60 +34,52 @@ export async function load_ae_obj_by_code__data_store({ } if (!code) { - console.log(`*ae_func* No code provided!`); - return null; - } - - if (!api_cfg.account_id) { - console.log(`*ae_func* No account_id found in API config!`); + if (log_lvl) console.log(`*ae_func* No code provided!`); return null; } try { - const get_ds_result = await api.get_data_store_obj_w_code({ - api_cfg: api_cfg, - data_store_code: code, - data_type: data_type, - timeout: timeout, - log_lvl: log_lvl + const get_ds_result = await api.get_data_store_v3({ + api_cfg, + code, + log_lvl }); if (!get_ds_result) { - console.log('*ae_func* No results returned.'); + if (log_lvl) console.log('*ae_func* No results returned.'); return null; } - if (log_lvl) { - console.log(`*ae_func* Got a result for code ${code}`); - } + const ds_id = get_ds_result.data_store_id_random || get_ds_result.id_random; - if (!get_ds_result.data_store_id_random) { - console.log('*ae_func* Something went wrong? No data store ID found.'); + if (!ds_id) { + if (log_lvl) console.log('*ae_func* Something went wrong? No data store ID found.'); return null; } - let return_this: any = null; - - // Simplified data extraction - if (data_type === 'html') { - return_this = get_ds_result.html; - } else if (data_type === 'json') { - return_this = get_ds_result.json; - } else { - return_this = get_ds_result.text; - } + // Map content fields for convenience + const text_val = get_ds_result.text || ''; + const json_val = get_ds_result.json || (get_ds_result.json_str ? JSON.parse(get_ds_result.json_str) : null); + + const mapped_ds: ae_DataStore = { + ...get_ds_result, + id: ds_id, + text: text_val, + html: text_val, // Map text to html by default + json: json_val + }; if (save_idb && browser) { - const key_prefix = 'ae_ds__'; - if (log_lvl) { - console.log(`*ae_func* localStorage key: ${code}, value:`, get_ds_result); - } - localStorage.setItem(`${key_prefix}${code}`, JSON.stringify(get_ds_result)); + const { db_core } = await import('./db_core'); + await db_core.data_store.put(mapped_ds); } - return return_this; + if (data_type === 'html') return mapped_ds.html; + if (data_type === 'json') return mapped_ds.json; + return mapped_ds.text; + } catch (error) { - console.log('*ae_func* No results returned or failed.', error); + if (log_lvl) console.error('*ae_func* Fetch failed.', error); return null; } } diff --git a/src/lib/elements/element_data_store_v3_alpha.svelte b/src/lib/elements/element_data_store_v3.svelte similarity index 70% rename from src/lib/elements/element_data_store_v3_alpha.svelte rename to src/lib/elements/element_data_store_v3.svelte index 57cc5347..b6558118 100644 --- a/src/lib/elements/element_data_store_v3_alpha.svelte +++ b/src/lib/elements/element_data_store_v3.svelte @@ -9,6 +9,7 @@ import { db_core } from '$lib/ae_core/db_core'; import { ae_util } from '$lib/ae_utils/ae_utils'; import type { key_val } from '$lib/stores/ae_stores'; + import type { ae_DataStore } from '$lib/types/ae_types'; interface Props { log_lvl?: number; @@ -28,7 +29,7 @@ ds_loaded?: boolean; debug?: boolean; ds_loading_status?: string; - val_sql?: null | key_val; + val_sql?: null | any; } let { @@ -57,62 +58,81 @@ let ds_submit_results: Promise | key_val | undefined = $state(); // Dexie LiveQuery for data store + // This derived observable will automatically update when dependencies change let lq__ds_obj = $derived( liveQuery(async () => { const current_code = ds_code; - const account_id = $slct.account_id; + const account_id = $ae_loc.account_id; const current_for_type = for_type; const current_for_id = for_id; if (!current_code) return null; - if (log_lvl > 1) console.log(`ae_e_data_store [${current_code}]: LQ Lookup...`, { account_id, current_for_type, current_for_id }); + if (log_lvl) console.log(`ae_e_data_store [${current_code}]: LQ Lookup...`, { account_id, current_for_type, current_for_id }); // Hierarchical Local Lookup (Specific -> Account -> Global) let result = null; - // 1. Specific Lookup - if (current_for_type && current_for_id) { - result = await db_core.data_store - .where('[code+for_type+for_id_random]') - .equals([current_code, current_for_type, current_for_id]) - .first(); - } + // 0. Code Only Lookup + // NOTE: Why this works. There should only be one record per code in the *local* Dexie DB. This is correct in 99.9% of cases. + if (log_lvl) console.log(`ae_e_data_store [${current_code}]: Trying Specific Code Lookup...`); + result = await db_core.data_store + .where('code') + .equals(current_code) + .first(); - // 2. Account Lookup - if (!result && account_id) { - result = await db_core.data_store - .where('[code+account_id_random+for_type]') - .equals([current_code, account_id, null]) - .first(); - } + // // 1. Specific Lookup + // if (current_for_type && current_for_id) { + // result = await db_core.data_store + // .where('[code+for_type+for_id_random]') + // .equals([current_code, current_for_type, current_for_id]) + // .first(); + // } - // 3. Global Lookup - if (!result) { - result = await db_core.data_store - .where('[code+account_id_random+for_type]') - .equals([current_code, null, null]) - .first(); - } + // // 2. Account Lookup + // if (!result && account_id) { + // result = await db_core.data_store + // .where('[code+account_id_random+for_type]') + // .equals([current_code, account_id, null]) + // .first(); + // } - if (log_lvl > 1) console.log(`ae_e_data_store [${current_code}]: LQ Result:`, result); - - // Update loaded status - ds_loaded = !!result; - if (result) ds_loading_status = 'loaded'; + // // 3. Global Lookup + // if (!result) { + // result = await db_core.data_store + // .where('[code+account_id_random+for_type]') + // .equals([current_code, null, null]) + // .first(); + // } return result; }) ); + // Sync status and bound props when the live data changes + $effect(() => { + const entry = $lq__ds_obj as ae_DataStore | null; + + untrack(() => { + ds_loaded = !!entry; + if (entry) { + ds_loading_status = 'loaded'; + // Handle val_sql binding if type is sql + if (ds_type === 'sql') { + val_sql = entry.text || entry.html || null; + } + } + }); + }); + // Initial Trigger & Context Change Guard $effect(() => { const account_id = $slct.account_id; const api_ready = !!$ae_api?.base_url; - - if (browser && api_ready && account_id) { - // Only trigger if not loaded or if we want a fresh check - if (!trigger) trigger = 'load__ds__code'; + const entry = $lq__ds_obj; + + if (browser && api_ready && !entry && ds_loading_status === 'starting') { + trigger = 'load__ds__code'; } }); @@ -137,7 +157,7 @@ async function load_data_store() { ds_loading_status = 'loading'; const api_cfg = untrack(() => $ae_api); - + if (log_lvl) console.log(`ae_e_data_store [${ds_code}]: Fetching...`); try { @@ -150,11 +170,14 @@ log_lvl: log_lvl }); + // V3 API structured check + const is_error = ds_results?.meta?.success === false; const status_code = ds_results?.meta?.status_code || (ds_results === false ? 500 : 200); - // Fallback to Global if not found or unauthorized for account - if (!ds_results || status_code === 403 || status_code === 401) { - if (log_lvl) console.log(`ae_e_data_store [${ds_code}]: Trying global fallback.`); + // Fallback to Global if not found (404), unauthorized (403/401), or explicitly failed + if (!ds_results || is_error || status_code === 404 || status_code === 403 || status_code === 401) { + if (log_lvl) console.log(`ae_e_data_store [${ds_code}]: Not found in context (Status ${status_code}). Trying global fallback.`); + ds_results = await api.get_data_store_v3({ api_cfg, code: ds_code, @@ -163,18 +186,25 @@ }); } - const ds_id = ds_results?.data_store_id_random || ds_results?.id_random || ds_results?.id || ds_results?.data_store_id; + const ds_id = ds_results?.data_store_id || ds_results?.id; if (ds_results && ds_id) { + // Map fields correctly for V3 alignment + const text_val = ds_results.text || ''; + const json_val = ds_results.json || (ds_results.json_str ? JSON.parse(ds_results.json_str) : null); + // Save to Dexie - const ds_to_save = { + const ds_to_save: ae_DataStore = { ...ds_results, id: ds_id, - data_store_id: ds_id, - data_store_id_random: ds_id, + data_store_id: ds_results.data_store_id || ds_id, + // data_store_id_random: ds_id, account_id: ds_results.account_id_random || ds_results.account_id, - account_id_random: ds_results.account_id_random || ds_results.account_id, - updated_on: ds_results.updated_on || new Date().toISOString() + // account_id_random: ds_results.account_id_random || ds_results.account_id, + updated_on: ds_results.updated_on || new Date().toISOString(), + text: text_val, + html: text_val, // Default map text to html + json: json_val }; await db_core.data_store.put(ds_to_save); @@ -214,10 +244,17 @@ account_id_random: data_store_di.ds_use_account_id ? (data_store_di.ds_account_id ?? $slct.account_id) : null }; + const content_val = data_store_di.ds_value; if (data_store_do.type === 'json') { - data_store_do.json = data_store_di.ds_value; + data_store_do.json = content_val; + try { + // Ensure it's valid JSON if stringified + if (typeof content_val === 'string') JSON.parse(content_val); + } catch (e) { + console.error("Invalid JSON content"); + } } else { - data_store_do.text = data_store_di.ds_value; + data_store_do.text = content_val; } const api_cfg = untrack(() => $ae_api); @@ -270,17 +307,21 @@
+ {#if $lq__ds_obj} {#if debug || $ae_loc.debug === 'debug'} -
-ID: {$lq__ds_obj.id}
-Code: {$lq__ds_obj.code}
-Name: {$lq__ds_obj.name}
-Type: {$lq__ds_obj.type}
-Created: {$lq__ds_obj.created_on}
-Updated: {$lq__ds_obj.updated_on}
-Account: {$lq__ds_obj.account_id_random || 'Global / NULL'}
+        Debug is ON!
+            
+    ID: {$lq__ds_obj.id}
+    Code: {$lq__ds_obj.code}
+    Name: {$lq__ds_obj.name}
+    Type: {$lq__ds_obj.type}
+    Created: {$lq__ds_obj.created_on}
+    Updated: {$lq__ds_obj.updated_on}
+    Account: {$lq__ds_obj.account_id_random || 'Global / NULL'}
             
+ +
{/if} {$lq__ds_obj.type === 'json' ? JSON.stringify($lq__ds_obj.json, null, 2) : ($lq__ds_obj.text || $lq__ds_obj.html || '')} + >{$lq__ds_obj.type === 'json' ? (typeof $lq__ds_obj.json === 'string' ? $lq__ds_obj.json : JSON.stringify($lq__ds_obj.json, null, 2)) : ($lq__ds_obj.text || $lq__ds_obj.html || '')}
@@ -348,17 +389,21 @@ Account: {$lq__ds_obj.account_id_random || 'Global / NULL'} - {#if $lq__ds_obj.type === 'html' && $lq__ds_obj.html} - {@html $lq__ds_obj.html} - {:else if $lq__ds_obj.type === 'text' && $lq__ds_obj.text} -
{$lq__ds_obj.text}
+ {#if show_view} + {#if $lq__ds_obj.type === 'html' && $lq__ds_obj.html} + {@html $lq__ds_obj.html} + {:else if $lq__ds_obj.type === 'text' && $lq__ds_obj.text} +
{$lq__ds_obj.text}
+ {:else if $lq__ds_obj.type === 'sql' && $lq__ds_obj.text} + {#if debug}
SQL: {$lq__ds_obj.text}
{/if} + {/if} {/if} {#if $ae_loc.edit_mode && ($ae_loc.manager_access || (show_edit_btn && $ae_loc.administrator_access))}
{/if} - - \ No newline at end of file diff --git a/src/routes/testing/data_store_v3/+page.svelte b/src/routes/testing/data_store_v3/+page.svelte index 45f4967a..3bf27a16 100644 --- a/src/routes/testing/data_store_v3/+page.svelte +++ b/src/routes/testing/data_store_v3/+page.svelte @@ -1,20 +1,28 @@