@tanstack/store 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/cjs/alien.cjs +345 -0
  2. package/dist/cjs/alien.cjs.map +1 -0
  3. package/dist/cjs/alien.d.cts +57 -0
  4. package/dist/cjs/atom.cjs +222 -0
  5. package/dist/cjs/atom.cjs.map +1 -0
  6. package/dist/cjs/atom.d.cts +16 -0
  7. package/dist/cjs/batch.cjs +15 -0
  8. package/dist/cjs/batch.cjs.map +1 -0
  9. package/dist/cjs/batch.d.cts +1 -0
  10. package/dist/cjs/index.cjs +8 -12
  11. package/dist/cjs/index.cjs.map +1 -1
  12. package/dist/cjs/index.d.cts +3 -4
  13. package/dist/cjs/store.cjs +22 -29
  14. package/dist/cjs/store.cjs.map +1 -1
  15. package/dist/cjs/store.d.cts +11 -30
  16. package/dist/cjs/types.d.cts +47 -20
  17. package/dist/esm/alien.d.ts +57 -0
  18. package/dist/esm/alien.js +345 -0
  19. package/dist/esm/alien.js.map +1 -0
  20. package/dist/esm/atom.d.ts +16 -0
  21. package/dist/esm/atom.js +222 -0
  22. package/dist/esm/atom.js.map +1 -0
  23. package/dist/esm/batch.d.ts +1 -0
  24. package/dist/esm/batch.js +15 -0
  25. package/dist/esm/batch.js.map +1 -0
  26. package/dist/esm/index.d.ts +3 -4
  27. package/dist/esm/index.js +8 -12
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/esm/store.d.ts +11 -30
  30. package/dist/esm/store.js +23 -30
  31. package/dist/esm/store.js.map +1 -1
  32. package/dist/esm/types.d.ts +47 -20
  33. package/package.json +6 -7
  34. package/src/alien.ts +654 -0
  35. package/src/atom.ts +298 -0
  36. package/src/batch.ts +12 -0
  37. package/src/index.ts +3 -4
  38. package/src/store.ts +33 -72
  39. package/src/types.ts +60 -24
  40. package/dist/cjs/derived.cjs +0 -130
  41. package/dist/cjs/derived.cjs.map +0 -1
  42. package/dist/cjs/derived.d.cts +0 -50
  43. package/dist/cjs/effect.cjs +0 -24
  44. package/dist/cjs/effect.cjs.map +0 -1
  45. package/dist/cjs/effect.d.cts +0 -18
  46. package/dist/cjs/scheduler.cjs +0 -103
  47. package/dist/cjs/scheduler.cjs.map +0 -1
  48. package/dist/cjs/scheduler.d.cts +0 -27
  49. package/dist/cjs/types.cjs +0 -7
  50. package/dist/cjs/types.cjs.map +0 -1
  51. package/dist/esm/derived.d.ts +0 -50
  52. package/dist/esm/derived.js +0 -130
  53. package/dist/esm/derived.js.map +0 -1
  54. package/dist/esm/effect.d.ts +0 -18
  55. package/dist/esm/effect.js +0 -24
  56. package/dist/esm/effect.js.map +0 -1
  57. package/dist/esm/scheduler.d.ts +0 -27
  58. package/dist/esm/scheduler.js +0 -103
  59. package/dist/esm/scheduler.js.map +0 -1
  60. package/dist/esm/types.js +0 -7
  61. package/dist/esm/types.js.map +0 -1
  62. package/src/derived.ts +0 -219
  63. package/src/effect.ts +0 -42
  64. package/src/scheduler.ts +0 -146
@@ -1,5 +1,4 @@
1
- export * from './derived.js';
2
- export * from './effect.js';
3
- export * from './store.js';
4
1
  export * from './types.js';
5
- export * from './scheduler.js';
2
+ export * from './atom.js';
3
+ export * from './store.js';
4
+ export * from './batch.js';
package/dist/esm/index.js CHANGED
@@ -1,17 +1,13 @@
1
- import { Derived } from "./derived.js";
2
- import { Effect } from "./effect.js";
3
- import { Store } from "./store.js";
4
- import { isUpdaterFunction } from "./types.js";
5
- import { __depsThatHaveWrittenThisTick, __derivedToStore, __flush, __storeToDerived, batch } from "./scheduler.js";
1
+ import { createAsyncAtom, createAtom, flush, toObserver } from "./atom.js";
2
+ import { Store, createStore } from "./store.js";
3
+ import { batch } from "./batch.js";
6
4
  export {
7
- Derived,
8
- Effect,
9
5
  Store,
10
- __depsThatHaveWrittenThisTick,
11
- __derivedToStore,
12
- __flush,
13
- __storeToDerived,
14
6
  batch,
15
- isUpdaterFunction
7
+ createAsyncAtom,
8
+ createAtom,
9
+ createStore,
10
+ flush,
11
+ toObserver
16
12
  };
17
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
@@ -1,31 +1,12 @@
1
- import { AnyUpdater, Listener } from './types.js';
2
- export interface StoreOptions<TState, TUpdater extends AnyUpdater = (cb: TState) => TState> {
3
- /**
4
- * Replace the default update function with a custom one.
5
- */
6
- updateFn?: (previous: TState) => (updater: TUpdater) => TState;
7
- /**
8
- * Called when a listener subscribes to the store.
9
- *
10
- * @return a function to unsubscribe the listener
11
- */
12
- onSubscribe?: (listener: Listener<TState>, store: Store<TState, TUpdater>) => () => void;
13
- /**
14
- * Called after the state has been updated, used to derive other state.
15
- */
16
- onUpdate?: () => void;
17
- }
18
- export declare class Store<TState, TUpdater extends AnyUpdater = (cb: TState) => TState> {
19
- listeners: Set<Listener<TState>>;
20
- state: TState;
21
- prevState: TState;
22
- options?: StoreOptions<TState, TUpdater>;
23
- constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>);
24
- subscribe: (listener: Listener<TState>) => () => void;
25
- /**
26
- * Update the store state safely with improved type checking
27
- */
28
- setState(updater: (prevState: TState) => TState): void;
29
- setState(updater: TState): void;
30
- setState(updater: TUpdater): void;
1
+ import { Observer, Subscription } from './types.js';
2
+ export declare class Store<T> {
3
+ private atom;
4
+ constructor(getValue: (prev?: NoInfer<T>) => T);
5
+ constructor(initialValue: T);
6
+ setState(updater: (prev: T) => T): void;
7
+ get state(): T;
8
+ get(): T;
9
+ subscribe(observerOrFn: Observer<T> | ((value: T) => void)): Subscription;
31
10
  }
11
+ export declare function createStore<T>(getValue: (prev?: NoInfer<T>) => T): Store<T>;
12
+ export declare function createStore<T>(initialValue: T): Store<T>;
package/dist/esm/store.js CHANGED
@@ -1,38 +1,31 @@
1
- import { __flush } from "./scheduler.js";
2
- import { isUpdaterFunction } from "./types.js";
1
+ import { createAtom, toObserver } from "./atom.js";
3
2
  class Store {
4
- constructor(initialState, options) {
5
- this.listeners = /* @__PURE__ */ new Set();
6
- this.subscribe = (listener) => {
7
- var _a, _b;
8
- this.listeners.add(listener);
9
- const unsub = (_b = (_a = this.options) == null ? void 0 : _a.onSubscribe) == null ? void 0 : _b.call(_a, listener, this);
10
- return () => {
11
- this.listeners.delete(listener);
12
- unsub == null ? void 0 : unsub();
13
- };
14
- };
15
- this.prevState = initialState;
16
- this.state = initialState;
17
- this.options = options;
3
+ constructor(valueOrFn) {
4
+ this.atom = createAtom(
5
+ valueOrFn
6
+ );
18
7
  }
19
8
  setState(updater) {
20
- var _a, _b, _c;
21
- this.prevState = this.state;
22
- if ((_a = this.options) == null ? void 0 : _a.updateFn) {
23
- this.state = this.options.updateFn(this.prevState)(updater);
24
- } else {
25
- if (isUpdaterFunction(updater)) {
26
- this.state = updater(this.prevState);
27
- } else {
28
- this.state = updater;
29
- }
30
- }
31
- (_c = (_b = this.options) == null ? void 0 : _b.onUpdate) == null ? void 0 : _c.call(_b);
32
- __flush(this);
9
+ this.atom.set(updater);
33
10
  }
11
+ get state() {
12
+ return this.atom.get();
13
+ }
14
+ get() {
15
+ return this.state;
16
+ }
17
+ subscribe(observerOrFn) {
18
+ return this.atom.subscribe(toObserver(observerOrFn));
19
+ }
20
+ }
21
+ function createStore(valueOrFn) {
22
+ if (typeof valueOrFn === "function") {
23
+ return new Store(valueOrFn);
24
+ }
25
+ return new Store(valueOrFn);
34
26
  }
35
27
  export {
36
- Store
28
+ Store,
29
+ createStore
37
30
  };
38
31
  //# sourceMappingURL=store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sources":["../../src/store.ts"],"sourcesContent":["import { __flush } from './scheduler'\nimport { isUpdaterFunction } from './types'\nimport type { AnyUpdater, Listener, Updater } from './types'\n\nexport interface StoreOptions<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n /**\n * Replace the default update function with a custom one.\n */\n updateFn?: (previous: TState) => (updater: TUpdater) => TState\n /**\n * Called when a listener subscribes to the store.\n *\n * @return a function to unsubscribe the listener\n */\n onSubscribe?: (\n listener: Listener<TState>,\n store: Store<TState, TUpdater>,\n ) => () => void\n /**\n * Called after the state has been updated, used to derive other state.\n */\n onUpdate?: () => void\n}\n\nexport class Store<\n TState,\n TUpdater extends AnyUpdater = (cb: TState) => TState,\n> {\n listeners = new Set<Listener<TState>>()\n state: TState\n prevState: TState\n options?: StoreOptions<TState, TUpdater>\n\n constructor(initialState: TState, options?: StoreOptions<TState, TUpdater>) {\n this.prevState = initialState\n this.state = initialState\n this.options = options\n }\n\n subscribe = (listener: Listener<TState>) => {\n this.listeners.add(listener)\n const unsub = this.options?.onSubscribe?.(listener, this)\n return () => {\n this.listeners.delete(listener)\n unsub?.()\n }\n }\n\n /**\n * Update the store state safely with improved type checking\n */\n setState(updater: (prevState: TState) => TState): void\n setState(updater: TState): void\n setState(updater: TUpdater): void\n setState(updater: Updater<TState> | TUpdater): void {\n this.prevState = this.state\n\n if (this.options?.updateFn) {\n this.state = this.options.updateFn(this.prevState)(updater as TUpdater)\n } else {\n if (isUpdaterFunction(updater)) {\n this.state = updater(this.prevState)\n } else {\n this.state = updater as TState\n }\n }\n\n // Always run onUpdate, regardless of batching\n this.options?.onUpdate?.()\n\n // Attempt to flush\n __flush(this as never)\n }\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,MAGX;AAAA,EAMA,YAAY,cAAsB,SAA0C;AAL5E,SAAA,gCAAgB,IAAA;AAWhB,SAAA,YAAY,CAAC,aAA+B;;AAC1C,WAAK,UAAU,IAAI,QAAQ;AAC3B,YAAM,SAAQ,gBAAK,YAAL,mBAAc,gBAAd,4BAA4B,UAAU;AACpD,aAAO,MAAM;AACX,aAAK,UAAU,OAAO,QAAQ;AAC9B;AAAA,MACF;AAAA,IACF;AAZE,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA,EAiBA,SAAS,SAA2C;;AAClD,SAAK,YAAY,KAAK;AAEtB,SAAI,UAAK,YAAL,mBAAc,UAAU;AAC1B,WAAK,QAAQ,KAAK,QAAQ,SAAS,KAAK,SAAS,EAAE,OAAmB;AAAA,IACxE,OAAO;AACL,UAAI,kBAAkB,OAAO,GAAG;AAC9B,aAAK,QAAQ,QAAQ,KAAK,SAAS;AAAA,MACrC,OAAO;AACL,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AAGA,qBAAK,YAAL,mBAAc,aAAd;AAGA,YAAQ,IAAa;AAAA,EACvB;AACF;"}
1
+ {"version":3,"file":"store.js","sources":["../../src/store.ts"],"sourcesContent":["import { createAtom, toObserver } from './atom'\nimport type { Atom, Observer, Subscription } from './types'\n\nexport class Store<T> {\n private atom: Atom<T>\n constructor(getValue: (prev?: NoInfer<T>) => T)\n constructor(initialValue: T)\n constructor(valueOrFn: T | ((prev?: T) => T)) {\n // createAtom has overloads that return ReadonlyAtom<T> for functions and Atom<T> for values\n // Store always needs Atom<T> for setState, so we assert the return type\n this.atom = createAtom(\n valueOrFn as T | ((prev?: NoInfer<T>) => T),\n ) as Atom<T>\n }\n public setState(updater: (prev: T) => T) {\n this.atom.set(updater)\n }\n public get state() {\n return this.atom.get()\n }\n public get() {\n return this.state\n }\n public subscribe(\n observerOrFn: Observer<T> | ((value: T) => void),\n ): Subscription {\n return this.atom.subscribe(toObserver(observerOrFn))\n }\n}\n\nexport function createStore<T>(getValue: (prev?: NoInfer<T>) => T): Store<T>\nexport function createStore<T>(initialValue: T): Store<T>\nexport function createStore<T>(valueOrFn: T | ((prev?: T) => T)): Store<T> {\n if (typeof valueOrFn === 'function') {\n return new Store(valueOrFn as (prev?: NoInfer<T>) => T)\n }\n return new Store(valueOrFn)\n}\n"],"names":[],"mappings":";AAGO,MAAM,MAAS;AAAA,EAIpB,YAAY,WAAkC;AAG5C,SAAK,OAAO;AAAA,MACV;AAAA,IAAA;AAAA,EAEJ;AAAA,EACO,SAAS,SAAyB;AACvC,SAAK,KAAK,IAAI,OAAO;AAAA,EACvB;AAAA,EACA,IAAW,QAAQ;AACjB,WAAO,KAAK,KAAK,IAAA;AAAA,EACnB;AAAA,EACO,MAAM;AACX,WAAO,KAAK;AAAA,EACd;AAAA,EACO,UACL,cACc;AACd,WAAO,KAAK,KAAK,UAAU,WAAW,YAAY,CAAC;AAAA,EACrD;AACF;AAIO,SAAS,YAAe,WAA4C;AACzE,MAAI,OAAO,cAAc,YAAY;AACnC,WAAO,IAAI,MAAM,SAAqC;AAAA,EACxD;AACA,SAAO,IAAI,MAAM,SAAS;AAC5B;"}
@@ -1,23 +1,50 @@
1
- /**
2
- * @private
3
- */
4
- export type AnyUpdater = (prev: any) => any;
5
- /**
6
- * Type-safe updater that can be either a function or direct value
7
- */
8
- export type Updater<T> = ((prev: T) => T) | T;
9
- /**
10
- * @private
11
- */
12
- export interface ListenerValue<T> {
13
- readonly prevVal: T;
14
- readonly currentVal: T;
1
+ import { ReactiveNode } from './alien.js';
2
+ export type Selection<TSelected> = Readable<TSelected>;
3
+ export interface InteropSubscribable<T> {
4
+ subscribe: (observer: Observer<T>) => Subscription;
5
+ }
6
+ export type Observer<T> = {
7
+ next?: (value: T) => void;
8
+ error?: (err: unknown) => void;
9
+ complete?: () => void;
10
+ };
11
+ export interface Subscription {
12
+ unsubscribe: () => void;
13
+ }
14
+ export interface Subscribable<T> extends InteropSubscribable<T> {
15
+ subscribe: ((observer: Observer<T>) => Subscription) & ((next: (value: T) => void, error?: (error: any) => void, complete?: () => void) => Subscription);
16
+ }
17
+ export interface Readable<T> extends Subscribable<T> {
18
+ get: () => T;
19
+ }
20
+ export interface BaseAtom<T> extends Subscribable<T>, Readable<T> {
21
+ }
22
+ export interface InternalBaseAtom<T> extends Subscribable<T>, Readable<T> {
23
+ /** @internal */
24
+ _snapshot: T;
25
+ /** @internal */
26
+ _update: (getValue?: T | ((snapshot: T) => T)) => boolean;
27
+ }
28
+ export interface Atom<T> extends BaseAtom<T> {
29
+ /** Sets the value of the atom using a function. */
30
+ set: ((fn: (prevVal: T) => T) => void) & ((value: T) => void);
31
+ }
32
+ export interface AtomOptions<T> {
33
+ compare?: (prev: T, next: T) => boolean;
34
+ }
35
+ export type AnyAtom = BaseAtom<any>;
36
+ export interface InternalReadonlyAtom<T> extends InternalBaseAtom<T>, ReactiveNode {
15
37
  }
16
38
  /**
17
- * @private
18
- */
19
- export type Listener<T> = (value: ListenerValue<T>) => void;
20
- /**
21
- * Type guard to check if updater is a function
39
+ * An atom that is read-only and cannot be set.
40
+ *
41
+ * @example
42
+ *
43
+ * ```ts
44
+ * const atom = createAtom(() => 42);
45
+ * // @ts-expect-error - Cannot set a readonly atom
46
+ * atom.set(43);
47
+ * ```
22
48
  */
23
- export declare function isUpdaterFunction<T>(updater: Updater<T>): updater is (prev: T) => T;
49
+ export interface ReadonlyAtom<T> extends BaseAtom<T> {
50
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/store",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Framework agnostic type-safe store w/ reactive framework adapters",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "src"
42
42
  ],
43
43
  "devDependencies": {
44
- "@angular/core": "^19.2.15",
44
+ "@angular/core": "^21.1.2",
45
45
  "@preact/signals": "^1.3.2",
46
46
  "solid-js": "^1.9.9",
47
47
  "vue": "^3.5.22"
@@ -50,11 +50,10 @@
50
50
  "clean": "premove ./dist ./coverage",
51
51
  "test:eslint": "eslint ./src ./tests",
52
52
  "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"",
53
- "test:types:ts50": "node ../../node_modules/typescript50/lib/tsc.js",
54
- "test:types:ts51": "node ../../node_modules/typescript51/lib/tsc.js",
55
- "test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js",
56
- "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js",
57
- "test:types:ts54": "tsc",
53
+ "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js",
54
+ "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js",
55
+ "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js",
56
+ "test:types:ts59": "tsc",
58
57
  "test:lib": "vitest",
59
58
  "test:bench": "vitest bench",
60
59
  "test:lib:dev": "pnpm run test:lib --watch",