import { NotImplementedError } from '../utils/error.js' export const AssetType = Object.freeze({ Text: url => fetch(url).then(res => res.text()), ArrayBuffer: url => fetch(url).then(res => res.arrayBuffer()), Image: url => new Promise((resolve, reject) => { const image = new Image() image.onload = () => resolve(image) image.onerror = err => reject(err) image.src = url }) }) class StorageLayer { has(_key) { throw new NotImplementedError() } get(_key) { throw new NotImplementedError() } set(_key, _value) { throw new NotImplementedError() } } class MemoryStorage extends StorageLayer { #memory = new Map() has(key) { return this.#memory.has(key) } get(key) { return this.#memory.get(key) } set(key, value) { this.#memory.set(key, value) } } class LocalStorage extends StorageLayer { #cache = new MemoryStorage() has(key) { if (this.#cache.has(key)) { return true } else { const item = localStorage.getItem(key) if (item != null) { this.#cache.set(key, item) return true } return false } } get(key) { if (this.#cache.has(key)) { return this.#cache.get(key) } else { const item = localStorage.getItem(key) if (item != null) { this.#cache.set(key, item) return item } return null } } set(key, value) { this.#cache.set(key, value) localStorage.setItem(key, value) } } export class Assets { #storage = new LocalStorage() /** * * @param {UrlLike} url * @param {(url: UrlLike) => Promise} handler */ async load(url, handler = AssetType.ArrayBuffer) { if (this.#storage.has(url)) { return this.#storage.get(url) } try { const data = await handler(url) this.#storage.set(url, data) return data } catch (err) { console.error(err) } } /** * @param {UrlLike} url */ get(url) { return this.#storage.get(url) } }