fix(idaa): harden data sync against padStart crashes and fix Archive Content sort

- Hardened object processors in Archives and Posts modules to safely handle null 'sort' values, preventing runtime TypeErrors during data synchronization.
- Fixed inconsistent sorting in Archive Content list by correctly implementing descending order (sort then reverse) and adding a configuration loading guard to the liveQuery.
- Standardized safe data processing patterns in SVELTE_DEXIE_GUIDE.md.
- Performed minor cleanup and visibility logic hardening in Recovery Meetings module.
This commit is contained in:
Scott Idem
2026-02-05 12:27:26 -05:00
parent bd39fd3061
commit 2306f2d0c4
9 changed files with 104 additions and 63 deletions

View File

@@ -92,6 +92,42 @@ export function createLiveQueryStore<T>(query: () => T | Promise<T>) {
The `createLiveQueryStore` function creates a readable store that automatically updates whenever the data in the `friends` table changes. The `$friends` variable in the component will always contain the latest data from the database.
## Safe Data Processing for IndexedDB Sorting
When preparing data for IndexedDB, especially when creating composite sort keys, it is critical to handle `null` or `undefined` values safely to prevent runtime crashes that can interrupt the data synchronization process.
### 1. Safe String Padding
Attempting to call `.toString()` or `.padStart()` on a `null` or `undefined` value will throw a `TypeError`. This is a common pitfall when processing optional fields like `sort` or `group`.
**Bad Pattern (Crash Risk):**
```typescript
// Crashes if obj.sort is null or undefined
obj.tmp_sort_1 = `${obj.sort.toString().padStart(3, '0')}`;
obj.tmp_sort_2 = `${obj.sort?.toString().padStart(3, '0') ?? ''}`; // Still risky if chaining is misunderstood
```
**Good Pattern (Safe):**
```typescript
// Safely handle null/undefined by defaulting to 0 or an empty string BEFORE string manipulation
const sort_val = (obj.sort ?? 0).toString().padStart(3, '0');
```
### 2. Correct Sorting with Dexie
Dexie's `sortBy()` method returns a new array sorted by the specified key. It **ignores** previous `reverse()` calls on the collection. To achieve a descending sort, you must sort first and then reverse the resulting array.
**Incorrect (Ascending Sort Result):**
```typescript
// .reverse() is ignored by .sortBy()
let results = await db.table.where('id').equals(id).reverse().sortBy('sort_key');
```
**Correct (Descending Sort Result):**
```typescript
// Sort ascending first, then reverse the array
let results = await db.table.where('id').equals(id).sortBy('sort_key');
return results.reverse();
```
## Current Data Flow in `ae_journals` Module
The `ae_journals` module currently uses a manual, API-first caching strategy. It does not use Dexie.js's `liveQuery` function for reactivity.
@@ -105,4 +141,4 @@ The `ae_journals` module currently uses a manual, API-first caching strategy. It
### Future Improvements
The current implementation could be improved by refactoring it to use Dexie.js's `liveQuery` function. This would simplify the code, reduce boilerplate, and improve the reactivity of the application. By using `liveQuery`, the UI would automatically update whenever the data in the IndexedDB database changes, without the need for manual store updates.
The current implementation could be improved by refactoring it to use Dexie.js's `liveQuery` function. This would simplify the code, reduce boilerplate, and improve the reactivity of the application. By using `liveQuery`, the UI would automatically update whenever the data in the IndexedDB database changes, without the need for manual store updates.