What about Svelte? #144
Replies: 3 comments 1 reply
-
@jamesgpearce sorry for the tag, do you know about it? |
Beta Was this translation helpful? Give feedback.
-
Hi @frederikhors. Yes. I am tinkering with a small project where I use Svelte (4.2) + Vite (no Sveltekit) and TinyBase. Here's a simplified example of my setup: <!-- App.svelte -->
<script setup lang="ts">
import { db, getDbDogsByAge } from "../lib/db";
let dogs = [];
$: dogs = getDbDogsByAge();
db.addTableListener("dogs", () => {
dogs = getDbDogsByAge();
});
function addDog() {
db.setRow("dogs", "0004", {
name: "New Boi",
age: 0,
});
}
</script>
<h1>Dog List</h1>
<button on:click={addDog}>add new dog</button>
{#each dogs as dog}
<div>{dog.name}, of age {dog.age}</div>
{/each} // /lib/db.ts
import { createQueries, createStore } from "tinybase/with-schemas";
export const db = createStore().setTablesSchema({
dogs: {
name: { type: "string" },
age: { type: "number" },
},
});
db.setTables({
dogs: {
"0001": { name: "Fluffy", age: 3 },
"0002": { name: "Bingo", age: 10 },
"0003": { name: "Warmonger", age: 1 },
},
});
const queries = createQueries(db);
export const getDbDogsByAge = () => {
queries.setQueryDefinition("getDogs", "dogs", ({ select }) => {
select("name");
select("age");
});
return queries
.getResultSortedRowIds("getDogs", "age", true)
.map((rowId) => queries.getResultRow("dogs", rowId));
}; And it just works! Reactivity and all. The code above is a bit silly but you can separate things (schema, initialization, queries) in multiple files and maybe write wrappers to improve the listener syntax. I am even using typescript and it works well. Currently queries have a minimal type support, meaning that if I want autocompletion on my query's result I have to write by hand the result's type and cast it. Not ideal, but I can reuse the type I wrote when typing the db schema. A bit sad this is missing but it's super understandable... auto-typing those queries doesn't look easy. I am also adding persistence and all seems going smoothly. So I would suggest you to give it a try 👍 |
Beta Was this translation helpful? Give feedback.
-
I've been playing with Svelte myself here. I'm writing some store helpers to listen, I dont have all of the things covered, but what I have I'll post here, the rest is just more of the same: import { readable, writable } from 'svelte/store';
import { getContext, onDestroy } from 'svelte';
import type { Id, Relationships, Row, Store, Value } from 'tinybase';
export function getStore(): Store | undefined {
const { store }: { store: Store } = getContext('tinybase') || {};
return store;
}
export function getStoreForce(): Store {
const store = getStore();
if (!store) throw new Error('Store not found in context');
return store;
}
export function getRelationships() {
const { relationships }: { relationships: Relationships } = getContext('tinybase') || {};
return relationships;
}
export function useValue(id: Id, defaultValue?: Value) {
const store = getStoreForce();
const { subscribe, set } = writable(store.getValue(id) || defaultValue, () => {
const listener = store.addValueListener(id, (store, valueId, newValue) => {
set(newValue)
})
return () => store.delListener(listener)
});
return {
subscribe,
set: (x: Value) => {
store.setValue(id, x)
}
}
}
export function useTable(tableId: Id) {
const store = getStoreForce();
return readable(store.getTable(tableId), (set) => {
const listener = store.addTableListener(tableId, (store, tableId) => {
set(store.getTable(tableId));
})
return () => store.delListener(listener)
});
}
export function useRowIds(tableId: Id) {
const store = getStoreForce();
return readable(store.getRowIds(tableId), (set) => {
const listener = store.addRowIdsListener(tableId, (store, tableId) => {
set(store.getRowIds(tableId));
})
return () => store.delListener(listener)
});
}
export function useRow(tableId: Id, rowId: Id) {
const store = getStoreForce();
const { subscribe, set } = writable(store.getRow(tableId, rowId), () => {
const listener = store.addRowListener(tableId, rowId, () => {
set(store.getRow(tableId, rowId));
})
return () => store.delListener(listener)
});
return {
subscribe,
set: (x: Row) => {
store.setRow(tableId, rowId, x)
}
}
}
export function useCell(tableId: Id, rowId: Id, cellId: Id, defaultValue?: Value) {
const store = getStoreForce();
const { subscribe, set } = writable(store.getCell(tableId, rowId, cellId) || defaultValue, () => {
const listener = store.addCellListener(tableId, rowId, cellId, (store, tableId, rowId, cellId, newCell) => {
set(newCell)
})
return () => store.delListener(listener)
});
return {
subscribe,
set: (x: Value) => {
store.setCell(tableId, rowId, cellId, x)
}
}
}
export function useRelationshipLocalRowIds(relationshipId: Id, remoteRowId: Id) {
const relationships = getRelationships()
return readable(relationships.getLocalRowIds(relationshipId, remoteRowId), (set) => {
const listener = relationships.addLocalRowIdsListener(relationshipId, remoteRowId, (relationships, relationshipId, remoteRowId) => {
set(relationships.getLocalRowIds(relationshipId, remoteRowId));
})
return () => relationships.delListener(listener)
});
} So you get the store reactivity with them. |
Beta Was this translation helpful? Give feedback.
-
What about Svelte?
Is there a way to use it with Svelte right now?
Beta Was this translation helpful? Give feedback.
All reactions