elliott/resources
Elliott Johnson 1 week ago
parent 61d02fe850
commit bca87b92bf

@ -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) {

@ -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

@ -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 */
@ -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);
@ -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

@ -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

@ -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';
@ -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();

@ -20,7 +20,7 @@ export interface ALSContext {
string,
{
value: MaybePromise<unknown>;
transport: Transport<any> | undefined;
transport: Transport | undefined;
}
>;
}

@ -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;
};

@ -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';

@ -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;
@ -122,20 +123,22 @@ 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 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;
};

Loading…
Cancel
Save