Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
da3260f
checkpoint; hydratable and base resource work
elliott-with-the-longest-name-on-github Oct 8, 2025
4d766f8
checkpoint
elliott-with-the-longest-name-on-github Oct 11, 2025
7c8c1ad
maximum hydration
elliott-with-the-longest-name-on-github Oct 15, 2025
83643ce
upgrade devalue
elliott-with-the-longest-name-on-github Oct 15, 2025
61d02fe
Merge remote-tracking branch 'origin' into elliott/resources
elliott-with-the-longest-name-on-github Oct 15, 2025
bca87b9
checkpoint
elliott-with-the-longest-name-on-github Oct 15, 2025
82be388
chore: temporarily remove fetcher
elliott-with-the-longest-name-on-github Oct 15, 2025
25210c2
types
elliott-with-the-longest-name-on-github Oct 15, 2025
9c7da6c
only generate hydratables when there's some amount of content
elliott-with-the-longest-name-on-github Oct 15, 2025
5de6383
add hash
elliott-with-the-longest-name-on-github Oct 15, 2025
8449ea7
making progress i think
elliott-with-the-longest-name-on-github Oct 21, 2025
ef11dae
typegen
elliott-with-the-longest-name-on-github Oct 21, 2025
d36894a
it at least basically works
elliott-with-the-longest-name-on-github Oct 21, 2025
0c4ce5a
misc improvements
elliott-with-the-longest-name-on-github Oct 24, 2025
a2bff0c
split stuff out, fix treeshaking
elliott-with-the-longest-name-on-github Oct 29, 2025
2e292b1
cache observer
elliott-with-the-longest-name-on-github Oct 29, 2025
7ee0ce8
fix export
elliott-with-the-longest-name-on-github Oct 29, 2025
90b85d1
add imperative hydratable API
elliott-with-the-longest-name-on-github Oct 30, 2025
598dc30
fix types
elliott-with-the-longest-name-on-github Oct 30, 2025
2c08d4f
fix types
elliott-with-the-longest-name-on-github Oct 30, 2025
5adb3f1
test
elliott-with-the-longest-name-on-github Oct 31, 2025
8179c6a
tests
elliott-with-the-longest-name-on-github Oct 31, 2025
6873685
temp fix
elliott-with-the-longest-name-on-github Oct 31, 2025
8939bbf
fix never-expiring cache entries
elliott-with-the-longest-name-on-github Nov 4, 2025
0f6001d
misc
elliott-with-the-longest-name-on-github Nov 4, 2025
8667dab
Merge remote-tracking branch 'origin' into elliott/resources
elliott-with-the-longest-name-on-github Nov 4, 2025
200b011
types
elliott-with-the-longest-name-on-github Nov 4, 2025
816ddca
import
elliott-with-the-longest-name-on-github Nov 4, 2025
7d44a1d
remove cruft, fix some type errors
elliott-with-the-longest-name-on-github Nov 4, 2025
cc094c5
.js .js .js wah wah wah
elliott-with-the-longest-name-on-github Nov 4, 2025
c6da91f
if you ignore your problems they go away
elliott-with-the-longest-name-on-github Nov 4, 2025
b36ba6d
unused
elliott-with-the-longest-name-on-github Nov 4, 2025
d6f240a
better serialization
elliott-with-the-longest-name-on-github Nov 4, 2025
7d0451e
oops
elliott-with-the-longest-name-on-github Nov 4, 2025
cd7a71f
oops
elliott-with-the-longest-name-on-github Nov 5, 2025
0581bb9
tweak
elliott-with-the-longest-name-on-github Nov 5, 2025
5aa7598
tweak
elliott-with-the-longest-name-on-github Nov 5, 2025
08d755b
tweak
elliott-with-the-longest-name-on-github Nov 5, 2025
9a424cd
add errors
elliott-with-the-longest-name-on-github Nov 5, 2025
e28ced7
tweak hydratable API, add official errors
elliott-with-the-longest-name-on-github Nov 6, 2025
aaf2eb8
fix types
elliott-with-the-longest-name-on-github Nov 6, 2025
555e950
Merge remote-tracking branch 'origin' into elliott/resources
elliott-with-the-longest-name-on-github Nov 6, 2025
d5fef8b
types
elliott-with-the-longest-name-on-github Nov 6, 2025
3f24dd2
Update packages/svelte/src/internal/server/renderer.js
elliott-with-the-longest-name-on-github Nov 6, 2025
551572e
errors
elliott-with-the-longest-name-on-github Nov 6, 2025
998510c
Merge branch 'elliott/resources' of github.com:sveltejs/svelte into e…
elliott-with-the-longest-name-on-github Nov 6, 2025
f9123f4
Update packages/svelte/messages/client-errors/errors.md
elliott-with-the-longest-name-on-github Nov 6, 2025
d5e4af8
fixes
elliott-with-the-longest-name-on-github Nov 6, 2025
61706dd
Merge branch 'elliott/resources' of github.com:sveltejs/svelte into e…
elliott-with-the-longest-name-on-github Nov 6, 2025
0ff9656
fix
elliott-with-the-longest-name-on-github Nov 6, 2025
1a6b53b
chore: use public.d.ts as entry point for svelte/reactivity (#17124)
Rich-Harris Nov 7, 2025
141fd1e
reactive cache
elliott-with-the-longest-name-on-github Nov 8, 2025
eca531f
Merge branch 'elliott/resources' of github.com:sveltejs/svelte into e…
elliott-with-the-longest-name-on-github Nov 10, 2025
f9cdb76
caching
elliott-with-the-longest-name-on-github Nov 10, 2025
a715fa1
chore: tweak resource implementation (#17123)
Rich-Harris Nov 10, 2025
cc74b6d
Merge branch 'elliott/resources' of github.com:sveltejs/svelte into e…
elliott-with-the-longest-name-on-github Nov 10, 2025
85abdbd
whatever
elliott-with-the-longest-name-on-github Nov 13, 2025
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
checkpoint
  • Loading branch information
commit bca87b92bfec91191f684d501fb8e0eac4e8d97d
5 changes: 4 additions & 1 deletion packages/svelte/src/internal/client/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ export function is_runes() {

/**
* @template T
* @type {Hydratable<T>}
* @param {string} key
* @param {() => T} fn
* @param {{ transport?: Transport }} [options]
* @returns {Promise<T>}
*/
export function hydratable(key, fn, { transport } = {}) {
if (!hydrating) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */

import { compile } from 'path-to-regexp';
import { create_resource } from './create-resource.js';
import { create_resource } from './define-resource.js';

/**
* @template {Record<string, unknown>} TPathParams
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @import { Transport } from '#shared' */
import { hydratable } from '../../context.js';
import { tick } from '../../runtime';
import { render_effect } from '../effects';
import { tick } from '../../runtime.js';
import { render_effect } from '../effects.js';
import { Resource } from './resource.js';

/** @typedef {{ count: number, resource: Resource<any> }} Entry */
Expand All @@ -12,14 +13,14 @@ const cache = new Map();
* @template {unknown[]} [TArgs=[]]
* @template {typeof Resource} [TResource=typeof Resource]
* @param {string} name
* @param {(...args: TArgs) => Promise<TReturn>} fn
* @param {{ Resource?: TResource }} [options]
* @param {(...args: TArgs) => TReturn} fn
* @param {{ Resource?: TResource, transport?: Transport }} [options]
* @returns {(...args: TArgs) => Resource<TReturn>}
*/
export function create_resource(name, fn, options) {
export function define_resource(name, fn, options = {}) {
const ResolvedResource = options?.Resource ?? Resource;
return (...args) => {
const stringified_args = JSON.stringify(args);
const stringified_args = (options.transport?.stringify ?? JSON.stringify)(args);
const cache_key = `${name}:${stringified_args}`;
let entry = cache.get(cache_key);
const maybe_remove = create_remover(cache_key);
Expand All @@ -41,7 +42,9 @@ export function create_resource(name, fn, options) {

let resource = entry?.resource;
if (!resource) {
resource = new ResolvedResource(() => hydratable(cache_key, () => fn(...args)));
resource = new ResolvedResource(() =>
hydratable(cache_key, () => fn(...args), { transport: options.transport })
);
const entry = {
resource,
count: tracking ? 1 : 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @import { Source, Derived } from '#client' */
import { state, derived, set, get, tick } from '../../index.js';
import { deferred, noop } from '../../../shared/utils.js';
import { deferred } from '../../../shared/utils.js';

/**
* @template T
Expand Down
7 changes: 5 additions & 2 deletions packages/svelte/src/internal/server/context.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @import { ALSContext, SSRContext } from '#server' */
/** @import { AsyncLocalStorage } from 'node:async_hooks' */
/** @import { Hydratable } from '#shared' */
/** @import { Transport } from '#shared' */
import { DEV } from 'esm-env';
import * as e from './errors.js';

Expand Down Expand Up @@ -127,7 +127,10 @@ export async function save(promise) {

/**
* @template T
* @type {Hydratable<T>}
* @param {string} key
* @param {() => T} fn
* @param {{ transport?: Transport }} [options]
* @returns {Promise<T>}
*/
export async function hydratable(key, fn, { transport } = {}) {
const store = await get_render_store();
Expand Down
2 changes: 1 addition & 1 deletion packages/svelte/src/internal/server/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface ALSContext {
string,
{
value: MaybePromise<unknown>;
transport: Transport<any> | undefined;
transport: Transport | undefined;
}
>;
}
Expand Down
12 changes: 3 additions & 9 deletions packages/svelte/src/internal/shared/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,7 @@ export type Snapshot<T> = ReturnType<typeof $state.snapshot<T>>;

export type MaybePromise<T> = T | Promise<T>;

export type Hydratable<T> = (
key: string,
fn: () => T,
options?: { transport?: Transport<T> }
) => Promise<T>;

export type Transport<T> = {
stringify: (value: T) => string;
parse: (value: string) => T;
export type Transport = {
stringify: (value: unknown) => string;
parse: (value: string) => unknown;
};
2 changes: 1 addition & 1 deletion packages/svelte/src/reactivity/index-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ 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/resources/resource.js';
export { create_resource as createResource } from '../internal/client/reactivity/resources/create-resource.js';
export { define_resource as defineResource } from '../internal/client/reactivity/resources/define-resource.js';
export { create_fetcher as createFetcher } from '../internal/client/reactivity/resources/create-fetcher.js';
15 changes: 9 additions & 6 deletions packages/svelte/src/reactivity/index-server.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @import { StandardSchemaV1 } from '@standard-schema/spec' */
import { compile } from 'path-to-regexp';
/** @import { Transport } from '#shared' */
import { uneval } from 'devalue';
import { hydratable } from '../internal/server/context.js';

export const SvelteDate = globalThis.Date;
Expand Down Expand Up @@ -122,20 +123,22 @@
* @template {unknown[]} [TArgs=[]]
* @template {typeof Resource} [TResource=typeof Resource]
* @param {string} name
* @param {(...args: TArgs) => Promise<TReturn>} fn
* @param {{ Resource?: TResource }} [options]
* @param {(...args: TArgs) => TReturn} fn
* @param {{ Resource?: TResource, transport?: Transport }} [options]
* @returns {(...args: TArgs) => Resource<TReturn>}
*/
export function createResource(name, fn, options) {
export function defineResource(name, fn, options = {}) {
const ResolvedResource = options?.Resource ?? Resource;
return (...args) => {
const stringified_args = JSON.stringify(args);
const stringified_args = (options.transport?.stringify ?? JSON.stringify)(args);
const cache_key = `${name}:${stringified_args}`;
const entry = cache.get(cache_key);
if (entry) {
return entry;
}
const resource = new ResolvedResource(() => hydratable(cache_key, () => fn(...args)));
const resource = new ResolvedResource(() =>
hydratable(cache_key, () => fn(...args), { transport: options.transport })
);
cache.set(cache_key, resource);
return resource;
};
Expand Down Expand Up @@ -177,7 +180,7 @@
*/
export function createFetcher(url, options) {
const raw_pathname = url.split('//')[1].match(/(\/[^?#]*)/)?.[1] ?? '';
const populate_path = compile(raw_pathname);

Check failure on line 183 in packages/svelte/src/reactivity/index-server.js

View workflow job for this annotation

GitHub Actions / Lint

'compile' is not defined
/**
* @param {Parameters<Fetcher<any, any>>[0]} args
* @returns {Promise<any>}
Expand All @@ -199,5 +202,5 @@
}
return json;
};
return createResource(url.toString(), fn, options);

Check failure on line 205 in packages/svelte/src/reactivity/index-server.js

View workflow job for this annotation

GitHub Actions / Lint

'createResource' is not defined
}
Loading