Saving the new documentation for Svelte and Dexie made by Gemini. Saving changes made by Gemini to fix various things.

This commit is contained in:
Scott Idem
2025-11-17 14:09:33 -05:00
parent 02169f1cb9
commit c4fa35e86e
8 changed files with 149 additions and 30 deletions

View File

@@ -20,6 +20,10 @@ Additional Aether modules
## Documentation
* TODO.md
* Svelte - Introducing runes - https://svelte.dev/blog/runes
* Svelte - Breaking changes in runes mode - https://svelte.dev/docs/svelte/v5-migration-guide#Breaking-changes-in-runes-mode
* Dexie.js - Getting Started - https://dexie.org/docs/Tutorial/Getting-started
* Dexie.js - API Quick Reference - https://dexie.org/docs/API-Reference#quick-reference
## Ignored Directories

110
SVELTE_DEXIE_GUIDE.md Normal file
View File

@@ -0,0 +1,110 @@
# Svelte and Dexie.js Integration Guide
This document provides a guide to integrating Svelte (with a focus on Runes) and Dexie.js for building reactive web applications. It covers key concepts and best practices for managing reactivity between Svelte components and the Dexie.js database.
## Svelte 5 Migration Guide
Svelte 5 introduces "runes" as a new way to manage reactivity. This is a major change from previous versions of Svelte, and it's important to understand the breaking changes before migrating.
### Key Breaking Changes
* **`let` is no longer reactive:** In Svelte 4, any `let` variable declared in the top-level scope of a component was automatically reactive. In Svelte 5, you must explicitly declare reactive state using the `$state` rune.
* **`$:` is replaced by `$derived` and `$effect`:** The `$` label is no longer used for reactive statements. Instead, you should use the `$derived` rune for computed values and the `$effect` rune for side effects.
* **`export let` is replaced by `$props`:** Component props are now declared using the `$props` rune, which provides a more flexible and explicit way to define component APIs.
* **Event handling:** The `on:` directive is replaced by event attributes (e.g., `onclick`). Component events are now handled using callback props instead of `createEventDispatcher`.
* **Slots are replaced by snippets:** The `<slot>` element is replaced by the `{#snippet ...}` block, which provides a more powerful and flexible way to pass content to components.
For a complete list of breaking changes, refer to the [Svelte 5 migration guide](https://svelte.dev/docs/svelte/v5-migration-guide).
## Dexie.js Quick Reference
Dexie.js is a lightweight, minimalistic wrapper for IndexedDB that makes it easier to work with client-side databases.
### Key Classes and Methods
* **`Dexie`:** The main class for creating and managing IndexedDB databases.
* `new Dexie(databaseName)`: Creates a new database instance.
* `version(versionNumber).stores({ ... })`: Defines the database schema.
* **`Table`:** Represents an object store (table) in the database.
* `add(item)`: Adds a new item to the table.
* `put(item)`: Adds or updates an item in the table.
* `update(key, changes)`: Updates an existing item.
* `delete(key)`: Deletes an item by its primary key.
* `get(key)`: Retrieves an item by its primary key.
* `where(index)`: Starts a query using an index.
* `toArray()`: Retrieves all items from the table as an array.
* **`Collection`:** Represents a collection of items resulting from a query.
* `toArray()`: Retrieves all items in the collection as an array.
* `first()`: Retrieves the first item in the collection.
* `last()`: Retrieves the last item in the collection.
* `each(callback)`: Iterates over each item in the collection.
* `modify(changes)`: Updates all items in the collection.
* `delete()`: Deletes all items in the collection.
For a complete list of API methods, refer to the [Dexie.js API Reference](https://dexie.org/docs/API-Reference).
## Integrating Svelte Runes and Dexie.js
The combination of Svelte Runes and Dexie.js allows for the creation of highly reactive and efficient web applications.
### The `liveQuery` Function
Dexie.js provides a `liveQuery` function that returns an observable of the query result. This observable can be used to automatically update the UI whenever the data in the database changes.
### Using `liveQuery` with Svelte Runes
To use `liveQuery` with Svelte Runes, you can create a custom readable store that wraps the `liveQuery` observable. This store can then be used in your Svelte components to display and interact with the data.
**1. Create a `liveQuery` store:**
```typescript
import { liveQuery } from 'dexie';
import { readable } from 'svelte/store';
import { db } from './db'; // Your Dexie database instance
export function createLiveQueryStore<T>(query: () => T | Promise<T>) {
return readable<T | undefined>(undefined, (set) => {
const subscription = liveQuery(query).subscribe({
next: (result) => set(result),
error: (error) => console.error(error),
});
return () => subscription.unsubscribe();
});
}
```
**2. Use the `createLiveQueryStore` in your component:**
```html
<script>
import { createLiveQueryStore } from './stores';
import { db } from './db';
const friends = createLiveQueryStore(() => db.friends.toArray());
</script>
<ul>
{#if $friends}
{#each $friends as friend}
<li>{friend.name}</li>
{/each}
{/if}
</ul>
```
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.
## 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.
### Data Flow
1. **Fetch from API:** The `load_ae_obj_id__journal` and `load_ae_obj_li__journal` functions are used to fetch data from the API.
2. **Process Data:** The `process_ae_obj__journal_props` and `process_ae_obj__journal_entry_props` functions are used to process the data before it's saved to the database. This includes parsing Markdown, creating temporary sorting fields, and combining passcodes.
3. **Save to IndexedDB:** The `db_save_ae_obj_li__ae_obj` function is used to save the processed data to the `journal` and `journal_entry` tables in the `ae_journals_db` IndexedDB database.
4. **Manual Store Updates:** The Svelte stores in `src/lib/ae_journals/ae_journals_stores.ts` are manually updated with the fetched data.
### 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.

View File

@@ -14,7 +14,7 @@ import { db_events } from "$lib/ae_events/db_events";
import { ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/stores/ae_stores';
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/stores/ae_events_stores';
import Element_qr_scanner from '$lib/elements/element_qr_scanner.svelte';
import Element_qr_scanner from '$lib/element_qr_scanner_v2.svelte';
import Element_ae_crud from '$lib/elements/element_ae_crud.svelte';
import { goto } from '$app/navigation';

View File

@@ -21,7 +21,7 @@ import { db_events } from "$lib/ae_events/db_events";
import { ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/stores/ae_stores';
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/stores/ae_events_stores';
import Element_qr_scanner from '$lib/elements/element_qr_scanner.svelte';
import Element_qr_scanner from '$lib/element_qr_scanner_v2.svelte';
import Element_ae_crud from '$lib/elements/element_ae_crud.svelte';
import { goto } from '$app/navigation';

View File

@@ -1,6 +1,7 @@
<script lang="ts">
console.log(`ae_events_leads exhibit [slug] leads_add_scan.svelte`, $events_slct);
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { liveQuery } from "dexie";
import { db_events } from "$lib/ae_events/db_events";
@@ -9,9 +10,8 @@ import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/stores/ae_stor
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import Element_qr_scanner from '$lib/elements/element_qr_scanner.svelte';
import Element_qr_scanner_v2 from '$lib/elements/element_qr_scanner_v2.svelte';
import Element_qr_scanner_dev from '$lib/elements/element_qr_scanner_dev.svelte';
import Element_qr_scanner from '$lib/element_qr_scanner_v2.svelte';
// TEMPORARY: For testing and development???
@@ -84,7 +84,7 @@ async function handle_submit_form_search(event) {
search_submit_results = await events_func.search__event_badge({
api_cfg: $ae_api,
event_id: $event_exhibit_obj.event_id_random,
event_id: $event_exhibit_obj?.event_id_random,
fulltext_search_qry_str: search_str,
external_event_id: $events_loc.leads.default__external_registration_id
});
@@ -295,7 +295,7 @@ function handle_qr_camera(event: CustomEvent<any>) {
</span>
{#if $events_loc.leads.show_content__scan_alert}
<div class="border border-slate-500/10 p-2 preset-tonal-warning border border-warning-500 p-1">
<div class="border-slate-500/10 p-2 preset-tonal-warning">
<span class="fas fa-exclamation-triangle mx-1"></span>
<span>
<strong>Alert</strong>
@@ -306,10 +306,9 @@ function handle_qr_camera(event: CustomEvent<any>) {
>
<option value={'one'}>v1</option>
<option value={'two'}>v2</option>
<option value={"dev"}>Development</option>
</select>
<p>A bug was found late Monday that affects some mobile devices (cell phones and tablets). Incremental fixes have been added, but this issue has been difficult to address accoss all devices. We recommend most users stick with v1 (default). If you are not having any trouble and have no idea what this message is about, then this is what you want.</p>
<p>A bug was found late Monday that affects some mobile devices (cell phones and tablets). Incremental fixes have been added, but this issue has been difficult to address across all devices. We recommend most users stick with v1 (default). If you are not having any trouble and have no idea what this message is about, then this is what you want.</p>
<p>We recommend you try v2 if you are having trouble with the camera not starting or turning on. This version allows you to manually attempt to Allow Camera Access and to Start Scanning if it does not start on its own. This fix is not perfect. A permanent solution is actively being worked on in the development version.</p>
<p>A fix is in progress to address all devices. -2024-04-10 2:25 AM (Prague time)</p>
</span>
@@ -740,23 +739,14 @@ function handle_qr_camera(event: CustomEvent<any>) {
on:qr_camera={handle_qr_camera}
/>
{:else if $ae_loc.qr_scanner_version == 'two'}
<Element_qr_scanner_v2
<!-- v2 dev -->
<!-- <Element_qr_scanner_v2
start_qr_scanner={$events_sess.leads.qr_scan_start}
show_qr_scan_result={true}
show_qr_manual_badge_id_entry_option={true}
on:qr_scan_result={handle_qr_scan_result}
on:qr_camera={handle_qr_camera}
/>
<!-- v2 -->
{:else if $ae_loc.qr_scanner_version == 'dev'}
<Element_qr_scanner_dev
start_qr_scanner={$events_sess.leads.qr_scan_start}
show_qr_scan_result={true}
show_qr_manual_badge_id_entry_option={true}
on:qr_scan_result={handle_qr_scan_result}
on:qr_camera={handle_qr_camera}
/>
vDEV
/> -->
{:else}
<p>Please close this and select a QR Scanner version</p>

View File

@@ -380,16 +380,9 @@ $effect(() => {
<button
type="button"
onclick={() => {
// if ($journals_sess.show__modal_append__journal_entry_id) {
// // $journals_sess.show__modal_append__journal_entry_id = null;
// $journals_sess.show__modal_append__journal_entry_id = journals_journal_entry_obj?.id;
// tmp_entry_obj = journals_journal_entry_obj;
// } else {
// $journals_sess.show__modal_append__journal_entry_id = journals_journal_entry_obj?.id;
// tmp_entry_obj = journals_journal_entry_obj;
// }
$journals_sess.show__modal_append__journal_entry_id = journals_journal_entry_obj?.id;
tmp_entry_obj = journals_journal_entry_obj;
// Create a deep copy of the object for editing to prevent direct mutation of the liveQuery result.
tmp_entry_obj = JSON.parse(JSON.stringify(journals_journal_entry_obj));
}}
class="btn btn-icon btn-sm preset-tonal-surface border border-surface-500 hover:preset-filled-secondary-500 transition"
title="{$lq__journal_obj?.cfg_json?.entry_add_text == 'append' ? 'Append to Journal Entry' : 'Prepend to Journal Entry'}"

View File

@@ -0,0 +1,4 @@
{
"status": "interrupted",
"failedTests": []
}

18
tests/example.test.ts Normal file
View File

@@ -0,0 +1,18 @@
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('http://localhost:4173/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/SvelteKit/);
});
test('get started link', async ({ page }) => {
await page.goto('http://localhost:4173/');
// Click the get started link.
await page.getByRole('link', { name: 'Docs' }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Welcome' })).toBeVisible();
});