separate client/server entry points for svelte/store

pull/12799/head
Rich Harris 2 years ago
parent 87008f03e8
commit 424c86197a

@ -76,7 +76,8 @@
},
"./store": {
"types": "./types/index.d.ts",
"default": "./src/store/index.js"
"browser": "./src/store/index-client.js",
"default": "./src/store/index-server.js"
},
"./transition": {
"types": "./types/index.d.ts",

@ -1,7 +1,7 @@
/** @import { Task } from '#client' */
/** @import { SpringOpts, SpringUpdateOpts, TickContext } from './private.js' */
/** @import { Spring } from './public.js' */
import { writable } from '../store/index.js';
import { writable } from '../store/shared/index.js';
import { loop } from '../internal/client/loop.js';
import { raf } from '../internal/client/timing.js';
import { is_date } from './utils.js';

@ -1,7 +1,7 @@
/** @import { Task } from '../internal/client/types' */
/** @import { Tweened } from './public' */
/** @import { TweenedOptions } from './private' */
import { writable } from '../store/index.js';
import { writable } from '../store/shared/index.js';
import { raf } from '../internal/client/timing.js';
import { loop } from '../internal/client/loop.js';
import { linear } from '../easing/index.js';

@ -0,0 +1,165 @@
/** @import { Readable, Writable } from './public.js' */
import { noop } from '../internal/shared/utils.js';
import {
effect_root,
effect_tracking,
render_effect
} from '../internal/client/reactivity/effects.js';
import { source } from '../internal/client/reactivity/sources.js';
import { get as get_source, tick } from '../internal/client/runtime.js';
import { increment } from '../reactivity/utils.js';
import { get, writable } from './shared/index.js';
export { derived, get, readable, readonly, writable } from './shared/index.js';
/**
* @template V
* @overload
* @param {() => V} get
* @param {(v: V) => void} set
* @returns {Writable<V>}
*/
/**
* @template V
* @overload
* @param {() => V} get
* @returns {Readable<V>}
*/
/**
* Create a store from a function that returns state, and (to make a writable store), an
* optional second function that sets state.
*
* ```ts
* import { toStore } from 'svelte/store';
*
* let count = $state(0);
*
* const store = toStore(() => count, (v) => (count = v));
* ```
* @template V
* @param {() => V} get
* @param {(v: V) => void} [set]
* @returns {Writable<V> | Readable<V>}
*/
export function toStore(get, set) {
const store = writable(get(), (set) => {
let ran = false;
// TODO do we need a different implementation on the server?
const teardown = effect_root(() => {
render_effect(() => {
const value = get();
if (ran) set(value);
});
});
ran = true;
return teardown;
});
if (set) {
return {
set,
update: (fn) => set(fn(get())),
subscribe: store.subscribe
};
}
return {
subscribe: store.subscribe
};
}
/**
* @template V
* @overload
* @param {Writable<V>} store
* @returns {{ current: V }}
*/
/**
* @template V
* @overload
* @param {Readable<V>} store
* @returns {{ readonly current: V }}
*/
/**
* Convert a store to an object with a reactive `current` property. If `store`
* is a readable store, `current` will be a readonly property.
*
* ```ts
* import { fromStore, get, writable } from 'svelte/store';
*
* const store = writable(0);
*
* const count = fromStore(store);
*
* count.current; // 0;
* store.set(1);
* count.current; // 1
*
* count.current += 1;
* get(store); // 2
* ```
* @template V
* @param {Writable<V> | Readable<V>} store
*/
export function fromStore(store) {
let value = /** @type {V} */ (undefined);
let version = source(0);
let subscribers = 0;
let unsubscribe = noop;
function current() {
if (effect_tracking()) {
get_source(version);
render_effect(() => {
if (subscribers === 0) {
let ran = false;
unsubscribe = store.subscribe((v) => {
value = v;
if (ran) increment(version);
});
ran = true;
}
subscribers += 1;
return () => {
subscribers -= 1;
tick().then(() => {
if (subscribers === 0) {
unsubscribe();
}
});
};
});
return value;
}
return get(store);
}
if ('set' in store) {
return {
get current() {
return current();
},
set current(v) {
store.set(v);
}
};
}
return {
get current() {
return current();
}
};
}

@ -0,0 +1,101 @@
/** @import { Readable, Writable } from './public.js' */
import { get, writable } from './shared/index.js';
export { derived, get, readable, readonly, writable } from './shared/index.js';
/**
* @template V
* @overload
* @param {() => V} get
* @param {(v: V) => void} set
* @returns {Writable<V>}
*/
/**
* @template V
* @overload
* @param {() => V} get
* @returns {Readable<V>}
*/
/**
* Create a store from a function that returns state, and (to make a writable store), an
* optional second function that sets state.
*
* ```ts
* import { toStore } from 'svelte/store';
*
* let count = $state(0);
*
* const store = toStore(() => count, (v) => (count = v));
* ```
* @template V
* @param {() => V} get
* @param {(v: V) => void} [set]
* @returns {Writable<V> | Readable<V>}
*/
export function toStore(get, set) {
const store = writable(get());
if (set) {
return {
set,
update: (fn) => set(fn(get())),
subscribe: store.subscribe
};
}
return {
subscribe: store.subscribe
};
}
/**
* @template V
* @overload
* @param {Writable<V>} store
* @returns {{ current: V }}
*/
/**
* @template V
* @overload
* @param {Readable<V>} store
* @returns {{ readonly current: V }}
*/
/**
* Convert a store to an object with a reactive `current` property. If `store`
* is a readable store, `current` will be a readonly property.
*
* ```ts
* import { fromStore, get, writable } from 'svelte/store';
*
* const store = writable(0);
*
* const count = fromStore(store);
*
* count.current; // 0;
* store.set(1);
* count.current; // 1
*
* count.current += 1;
* get(store); // 2
* ```
* @template V
* @param {Writable<V> | Readable<V>} store
*/
export function fromStore(store) {
if ('set' in store) {
return {
get current() {
return get(store);
},
set current(v) {
store.set(v);
}
};
}
return {
get current() {
return get(store);
}
};
}

@ -48,4 +48,4 @@ interface Writable<T> extends Readable<T> {
export { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable };
export * from './index.js';
export * from './index-client.js';

@ -1,16 +1,8 @@
/** @import { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable } from './public' */
/** @import { Stores, StoresValues, SubscribeInvalidateTuple } from './private' */
import { noop, run_all } from '../internal/shared/utils.js';
import { safe_not_equal } from '../internal/client/reactivity/equality.js';
import {
effect_root,
effect_tracking,
render_effect
} from '../internal/client/reactivity/effects.js';
import { subscribe_to_store } from './utils.js';
import { source } from '../internal/client/reactivity/sources.js';
import { get as get_source, tick } from '../internal/client/runtime.js';
import { increment } from '../reactivity/utils.js';
/** @import { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable } from '../public.js' */
/** @import { Stores, StoresValues, SubscribeInvalidateTuple } from '../private.js' */
import { noop, run_all } from '../../internal/shared/utils.js';
import { safe_not_equal } from '../../internal/client/reactivity/equality.js';
import { subscribe_to_store } from '../utils.js';
/**
* @type {Array<SubscribeInvalidateTuple<any> | any>}
@ -221,155 +213,3 @@ export function get(store) {
// @ts-expect-error
return value;
}
/**
* @template V
* @overload
* @param {() => V} get
* @param {(v: V) => void} set
* @returns {Writable<V>}
*/
/**
* @template V
* @overload
* @param {() => V} get
* @returns {Readable<V>}
*/
/**
* Create a store from a function that returns state, and (to make a writable store), an
* optional second function that sets state.
*
* ```ts
* import { toStore } from 'svelte/store';
*
* let count = $state(0);
*
* const store = toStore(() => count, (v) => (count = v));
* ```
* @template V
* @param {() => V} get
* @param {(v: V) => void} [set]
* @returns {Writable<V> | Readable<V>}
*/
export function toStore(get, set) {
const store = writable(get(), (set) => {
let ran = false;
// TODO do we need a different implementation on the server?
const teardown = effect_root(() => {
render_effect(() => {
const value = get();
if (ran) set(value);
});
});
ran = true;
return teardown;
});
if (set) {
return {
set,
update: (fn) => set(fn(get())),
subscribe: store.subscribe
};
}
return {
subscribe: store.subscribe
};
}
/**
* @template V
* @overload
* @param {Writable<V>} store
* @returns {{ current: V }}
*/
/**
* @template V
* @overload
* @param {Readable<V>} store
* @returns {{ readonly current: V }}
*/
/**
* Convert a store to an object with a reactive `current` property. If `store`
* is a readable store, `current` will be a readonly property.
*
* ```ts
* import { fromStore, get, writable } from 'svelte/store';
*
* const store = writable(0);
*
* const count = fromStore(store);
*
* count.current; // 0;
* store.set(1);
* count.current; // 1
*
* count.current += 1;
* get(store); // 2
* ```
* @template V
* @param {Writable<V> | Readable<V>} store
*/
export function fromStore(store) {
let value = /** @type {V} */ (undefined);
let version = source(0);
let subscribers = 0;
let unsubscribe = noop;
function current() {
if (effect_tracking()) {
get_source(version);
render_effect(() => {
if (subscribers === 0) {
let ran = false;
unsubscribe = store.subscribe((v) => {
value = v;
if (ran) increment(version);
});
ran = true;
}
subscribers += 1;
return () => {
subscribers -= 1;
tick().then(() => {
if (subscribers === 0) {
unsubscribe();
}
});
};
});
return value;
}
return get(store);
}
if ('set' in store) {
return {
get current() {
return current();
},
set current(v) {
store.set(v);
}
};
}
return {
get current() {
return current();
}
};
}

@ -2305,6 +2305,17 @@ declare module 'svelte/store' {
*/
update(this: void, updater: Updater<T>): void;
}
export function toStore<V>(get: () => V, set: (v: V) => void): Writable<V>;
export function toStore<V>(get: () => V): Readable<V>;
export function fromStore<V>(store: Writable<V>): {
current: V;
};
export function fromStore<V>(store: Readable<V>): {
readonly current: V;
};
/**
* Creates a `Readable` store that allows reading by subscription.
*
@ -2346,18 +2357,6 @@ declare module 'svelte/store' {
* https://svelte.dev/docs/svelte-store#get
* */
export function get<T>(store: Readable<T>): T;
export function toStore<V>(get: () => V, set: (v: V) => void): Writable<V>;
export function toStore<V>(get: () => V): Readable<V>;
export function fromStore<V>(store: Writable<V>): {
current: V;
};
export function fromStore<V>(store: Readable<V>): {
readonly current: V;
};
/** One or more `Readable`s. */
type Stores = Readable<any> | [Readable<any>, ...Array<Readable<any>>] | Array<Readable<any>>;

Loading…
Cancel
Save