- Centralize project-wide documentation into a new /documentation directory. - Remove old, deprecated README guideline files. - Create a comprehensive AETHER_API_OBJECTS.md file detailing all API data models.
6.0 KiB
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
letis no longer reactive: In Svelte 4, anyletvariable declared in the top-level scope of a component was automatically reactive. In Svelte 5, you must explicitly declare reactive state using the$staterune.$:is replaced by$derivedand$effect: The$label is no longer used for reactive statements. Instead, you should use the$derivedrune for computed values and the$effectrune for side effects.export letis replaced by$props: Component props are now declared using the$propsrune, 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 ofcreateEventDispatcher. - 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.
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.
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:
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:
<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
- Fetch from API: The
load_ae_obj_id__journalandload_ae_obj_li__journalfunctions are used to fetch data from the API. - Process Data: The
process_ae_obj__journal_propsandprocess_ae_obj__journal_entry_propsfunctions are used to process the data before it's saved to the database. This includes parsing Markdown, creating temporary sorting fields, and combining passcodes. - Save to IndexedDB: The
db_save_ae_obj_li__ae_objfunction is used to save the processed data to thejournalandjournal_entrytables in theae_journals_dbIndexedDB database. - Manual Store Updates: The Svelte stores in
src/lib/ae_journals/ae_journals_stores.tsare 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.