بنقرة واحدة
svas
Async Svelte stores (svas): fetching, caching, revalidation, persistence. Use when UI presents data from the API.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Async Svelte stores (svas): fetching, caching, revalidation, persistence. Use when UI presents data from the API.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | svas |
| description | Async Svelte stores (svas): fetching, caching, revalidation, persistence. Use when UI presents data from the API. |
Stores that fetch lazily, cache, revalidate, and persist. Every store emits one of three types:
type Maybe<T, E extends Error = Error> = null | T | E
// null → no data yet (loading / cleared / not fetched)
// T → resolved value
// E → fetch error (errors are values, never thrown)
import {
value, values, collection, // stores
ok, ensure, having, awaited, once, // guards & awaiting
combined, sync, Async, // compose & render
type Maybe
} from 'svas'
Every store fetches on first subscribe, then auto-revalidates. Common options:
| Option | Meaning |
|---|---|
get | fetcher returning Promise<T | Error> |
revalidate | ms before re-fetch (default 300_000; Infinity disables) |
persist | mirror into local storage under this key |
session | use sessionStorage instead of localStorage |
stale | keep previous value visible while revalidating (default false) |
bind | Readable<unknown | null> — reset/clear store when bound store is null (tie data to a user) |
default | initial value when nothing is persisted |
All stores implements Readable interface from svelte/store.
Use persist whenever it makes sense to persist the data, it will vastly speed up the initial load.
If store contains user-bound data, use bind to reset the store when the user is logged out.
value<T> — one async valueWritable<T | null>. For single fetched values, auth tokens, transient UI flags.
const me = value<User>({ get: () => api.me(), persist: 'user' })
const seen = value<number>({ persist: 'seen', default: 0 }) // transient/local-only
Methods: set(v), update(fn), extract(): T | null (sync read), sync() (revalidate if stale).
values<T> — keyed cacheA map of independent Readable<Maybe<T>> lifecycles, one per key.
const products = values<Product>({ get: (id) => api.product(id), stale: true, persist: 'products' })
const one = products.get('42') // Readable<Maybe<Product>>, fetches if missing
products.set('42', next) // write by key
products.extract('42') // Product | null, sync
Methods: get(key, { fetch? }) · set(key, v, { stash? }) · reset(key) (restore stashed value) · extract(key) · delete(key) · clear().
Extra options: permanent (don't revalidate persisted entries on startup). stash: true on set remembers the prior persisted value so reset(key) can roll back — use for optimistic updates.
collection<T> — list of Identifiable itemsReadable<Maybe<T[]>>. Items must have { id: string }. Pass a values store to also observe items individually via get(id).
const todos = collection<Todo>({
get: () => api.todos(),
values: values<Todo>(), // enables todos.get(id) / extract(id)
stale: true,
persist: 'todos',
bind: session
})
Methods: subscribe · add(item) · set(item, { add? }) (replace by id; add inserts if absent) · update(id, fn, opts?) · delete(id) · replace(items) · get(id)/extract(id) (require values) · sync(): this · fetch(): Promise<this>.
Mutations mirror into the values store, so components subscribed via get(id) update without re-fetching.
Never use ?. on a Maybe<T> — an Error has no domain properties. Narrow first.
ok($store) // boolean type guard: narrows Maybe<T> → T (excludes null | Error)
ensure(store) // sync read, THROWS if null/Error — use when value must exist now (e.g. unsafe net requests in response to user action)
store.extract(key?) // sync read, T | null (ignores errors) — never throws
if (ok($todos)) $todos.length // typed as T
items.filter((i) => ok(i.account) && !i.account.deleted) // ✅ guard before access
await having(store) // first non-null value; REJECTS on Error — services needing auth
await awaited(store) // first non-null value; returns Error as a value (never rejects)
await once(store, (v) => v === 'ready') // first value satisfying a condition
<Async> — render a Maybe<Async store={todos}>
{#snippet awaited(todos)}
<!-- here todos are T[] -->
{#each todos as t}<Row {t} />{/each}
{/snippet}
{#snippet waiting()}<Spinner />{/snippet} <!-- optional; default loader otherwise -->
{#snippet error(e)}<Err {e} />{/snippet} <!-- optional; default error UI otherwise -->
</Async>
Props: store (required), awaited snippet (required), optional waiting / error snippets, silent (suppress default loader/error chrome). Combine with combined to await several at once.
combined(...stores)One Maybe from many: tuple when all resolve, first Error, else null. Spreadable.
<Async store={combined(account, todos)}>
{#snippet awaited([account, todos])}
<!-- here account is U and todos is T[] -->
<Profile {account} />
{#each todos as t}<Row {t} />{/each}
{/snippet}
</Async>
sync(store, item, { delete? })Conflict-free update.
T must implement interface Comparable { id: string; _version: number;_deleted?: number | null }
Merge a versioned item into a collection or value, respecting _version; removes on _deleted (unless delete: false). For applying server/realtime events.
events.on('todos.sync', (todo) => sync(todos, todo))
T | Error; check instanceof Error, never try/catch for expected failures.ok()/ensure()/extract(), never ?. on Maybe<T>.$store, <Async>, get, having, or .subscribe triggers it.For derived Maybe stores with live subscriptions/cleanup, realtime event wiring, linked/enriched entities, and optimistic update patterns, see references/patterns.md.