diff --git a/packages/svelte/src/internal/client/reactivity/cache.js b/packages/svelte/src/internal/client/reactivity/cache.js index 49142f0eda..05f427d634 100644 --- a/packages/svelte/src/internal/client/reactivity/cache.js +++ b/packages/svelte/src/internal/client/reactivity/cache.js @@ -4,9 +4,9 @@ import { active_effect, is_destroying_effect, tick } from '../runtime.js'; import { render_effect } from './effects.js'; import * as e from '../errors.js'; -/** @template T */ +/** @template [K=any], [V=any] */ export class ReactiveCache { - /** @type {Map>} */ + /** @type {Map>} */ #cache = new Map(); constructor() { @@ -16,9 +16,9 @@ export class ReactiveCache { } /** - * @param {string} key - * @param {() => T} fn - * @returns {T} + * @param {K} key + * @param {() => V} fn + * @returns {V} */ register(key, fn) { let entry = this.#cache.get(key); diff --git a/packages/svelte/src/internal/client/reactivity/resource.js b/packages/svelte/src/internal/client/reactivity/resource.js index 7f3780e680..66e7463406 100644 --- a/packages/svelte/src/internal/client/reactivity/resource.js +++ b/packages/svelte/src/internal/client/reactivity/resource.js @@ -4,6 +4,10 @@ import { state, derived, set, get, tick } from '../index.js'; import { deferred } from '../../shared/utils.js'; import { async_mode_flag } from '../../flags/index.js'; import * as e from '../errors.js'; +import { ReactiveCache } from './cache.js'; + +/** @type ReactiveCache, Resource> */ +const registry = new ReactiveCache(); /** * @template T @@ -78,6 +82,8 @@ class Resource { * @param {() => T} fn */ constructor(fn) { + // this is kind of kludgy, but the alternative is basically to write a copy of `cache` that is a `Set` instead of a `Map`, which seems dumb + registry.register(this, () => this); this.#fn = fn; this.#promise = state(this.#run()); } @@ -183,3 +189,12 @@ class Resource { set(this.#promise, Promise.resolve()); }; } + +/** @returns {Promise} */ +export async function refreshAll() { + let promises = []; + for (const resource of registry) { + promises.push(resource.refresh()); + } + await Promise.all(promises); +} diff --git a/packages/svelte/src/internal/server/reactivity/cache.js b/packages/svelte/src/internal/server/reactivity/cache.js index b46e2a252b..998547ce9b 100644 --- a/packages/svelte/src/internal/server/reactivity/cache.js +++ b/packages/svelte/src/internal/server/reactivity/cache.js @@ -2,7 +2,7 @@ import { async_mode_flag } from '../../flags/index.js'; import * as e from '../errors.js'; import { get_render_context } from '../render-context.js'; -/** @template T */ +/** @template [K=any], [V=any] */ export class ReactiveCache { #key = Symbol('ReactiveCache'); @@ -13,9 +13,9 @@ export class ReactiveCache { } /** - * @param {string} key - * @param {() => T} fn - * @returns {T} + * @param {K} key + * @param {() => V} fn + * @returns {V} */ register(key, fn) { const cache = this.#get_cache(); diff --git a/packages/svelte/src/internal/server/reactivity/resource.js b/packages/svelte/src/internal/server/reactivity/resource.js index d354c76359..c3f3fc0692 100644 --- a/packages/svelte/src/internal/server/reactivity/resource.js +++ b/packages/svelte/src/internal/server/reactivity/resource.js @@ -100,3 +100,7 @@ class Resource { this.#promise = Promise.resolve(); }; } + +export function refreshAll() { + throw new Error('TODO Cannot refreshAll resources on the server'); +} diff --git a/packages/svelte/src/internal/server/types.d.ts b/packages/svelte/src/internal/server/types.d.ts index 87dad63614..6b1cf6e1f2 100644 --- a/packages/svelte/src/internal/server/types.d.ts +++ b/packages/svelte/src/internal/server/types.d.ts @@ -23,7 +23,7 @@ export interface HydratableEntry { export interface RenderContext { hydratables: Map; - cache: Map>; + cache: Map>; } export interface SyncRenderOutput { diff --git a/packages/svelte/src/reactivity/index-client.js b/packages/svelte/src/reactivity/index-client.js index d8c22cef4a..8714d130ae 100644 --- a/packages/svelte/src/reactivity/index-client.js +++ b/packages/svelte/src/reactivity/index-client.js @@ -5,6 +5,6 @@ export { SvelteURL } from './url.js'; export { SvelteURLSearchParams } from './url-search-params.js'; export { MediaQuery } from './media-query.js'; export { createSubscriber } from './create-subscriber.js'; -export { resource } from '../internal/client/reactivity/resource.js'; +export { resource, refreshAll } from '../internal/client/reactivity/resource.js'; export { ReactiveCache } from '../internal/client/reactivity/cache.js'; export { fetcher } from '../internal/client/reactivity/fetcher.js'; diff --git a/packages/svelte/src/reactivity/index-server.js b/packages/svelte/src/reactivity/index-server.js index 1125cdbd21..cba4355a6b 100644 --- a/packages/svelte/src/reactivity/index-server.js +++ b/packages/svelte/src/reactivity/index-server.js @@ -1,5 +1,5 @@ /** @import { Resource as ResourceType } from '#shared' */ -export { resource } from '../internal/server/reactivity/resource.js'; +export { resource, refreshAll } from '../internal/server/reactivity/resource.js'; export { ReactiveCache } from '../internal/server/reactivity/cache.js'; export { fetcher } from '../internal/server/reactivity/fetcher.js';