svelte-asyncable
Version:
Super tiny, declarative, optimistic, async store for SvelteJS.
85 lines (74 loc) • 2.23 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('svelte/store')) :
typeof define === 'function' && define.amd ? define(['exports', 'svelte/store'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.asyncable = {}, global.store));
}(this, (function (exports, store) { 'use strict';
function asyncable(getter, setter = () => {}, stores = []) {
let resolve;
const initial = new Promise((res) => (resolve = res));
const derived$ = store.derived(stores, (values) => values);
const store$ = store.writable(initial, (set) => {
return derived$.subscribe(async (values = []) => {
let value = getter(...values);
if (value === undefined) return;
value = Promise.resolve(value);
set(value);
resolve(value);
});
});
async function set(newValue, oldValue) {
if (newValue === oldValue) return;
store$.set(Promise.resolve(newValue));
try {
await setter(newValue, oldValue);
} catch (err) {
store$.set(Promise.resolve(oldValue));
throw err;
}
}
return {
subscribe: store$.subscribe,
async update(reducer) {
if (!setter) return;
let oldValue;
let newValue;
try {
oldValue = await store.get(store$);
newValue = await reducer(shallowCopy(oldValue));
} finally {
await set(newValue, oldValue);
}
},
async set(newValue) {
if (!setter) return;
let oldValue;
try {
oldValue = await store.get(store$);
newValue = await newValue;
} finally {
await set(newValue, oldValue);
}
},
get() {
return store.get(store$);
},
};
}
function syncable(stores, initialValue) {
return store.derived(
stores,
($values, set) =>
(Array.isArray(stores) ? Promise.allSettled : Promise.resolve)
.call(Promise, $values)
.then(set),
initialValue
);
}
function shallowCopy(value) {
if (typeof value !== 'object' || value === null) return value;
return Array.isArray(value) ? [...value] : { ...value };
}
exports.asyncable = asyncable;
exports.syncable = syncable;
Object.defineProperty(exports, '__esModule', { value: true });
})));