Files
Website/src/components/stores/cached.ts
Chaoscaot 3c6d0f8528
All checks were successful
SteamWarCI Build successful
Fix
2025-06-29 14:00:09 +02:00

95 lines
2.8 KiB
TypeScript

/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { readonly, writable } from "svelte/store";
import type { Readable, Subscriber, Unsubscriber } from "svelte/store";
export interface Cached<T> extends Readable<T> {
reload: () => void;
future: Promise<T>;
}
export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
const store = writable<T>(normal);
const future = new Promise<T>((resolve) => {
let f = false;
store.subscribe((value) => {
if (f) {
resolve(value);
} else {
f = true;
}
});
});
let first = true;
const reload = () => {
init().then((data) => {
store.set(data);
});
};
return {
...readonly(store),
subscribe: (run: Subscriber<T>, invalidate?: (value?: T) => void): Unsubscriber => {
if (first) {
first = false;
reload();
}
return store.subscribe(run, invalidate);
},
reload,
future,
};
}
export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (arg: T) => Cached<K> {
const stores: Map<T, Cached<K>> = new Map();
return (arg: T) => {
if (stores.has(arg)) {
return stores.get(arg)!;
} else {
const store = writable<K>(normal);
let first = true;
const reload = () => {
init(arg).then((data) => {
store.set(data);
});
};
const cachedStore = {
...readonly(store),
subscribe: (run: Subscriber<K>, invalidate?: (value?: K) => void): Unsubscriber => {
if (first) {
first = false;
reload();
}
return store.subscribe(run, invalidate);
},
reload,
} as Cached<K>;
stores.set(arg, cachedStore);
return cachedStore;
}
};
}