Gathering detailed insights and metrics for @samsze/store
Gathering detailed insights and metrics for @samsze/store
Gathering detailed insights and metrics for @samsze/store
Gathering detailed insights and metrics for @samsze/store
npm install @samsze/store
Typescript
Module System
Node Version
NPM Version
68.8
Supply Chain
98.8
Quality
78.5
Maintenance
100
Vulnerability
100
License
TypeScript (98.22%)
Nix (1.78%)
Total Downloads
356
Last Day
2
Last Week
3
Last Month
9
Last Year
356
MIT License
1 Stars
26 Commits
1 Watchers
3 Branches
1 Contributors
Updated on Oct 02, 2024
Latest Version
1.1.2
Package Id
@samsze/store@1.1.2
Unpacked Size
72.73 kB
Size
14.48 kB
File Count
19
NPM Version
10.8.1
Node Version
22.4.1
Published on
Oct 02, 2024
Cumulative downloads
Total Downloads
Last Day
100%
2
Compared to previous day
Last Week
200%
3
Compared to previous week
Last Month
80%
9
Compared to previous month
Last Year
0%
356
Compared to previous year
store
A zustand-like state management solution.
Comparision with Zustand:
DeriveStore
which creates a store that derives its state from any number of other stores.1npm i @samsze/store
ObjectStore
(similar to Zustand-store)
1const counterStore = createObjectStore<CounterState>((set) => ({ 2 count: 0, 3 inc: () => set((state) => ({ count: state.count + 1 })), 4})); 5 6// Argument to `create*Store` function can be a plain object too 7const anotherStore = createObjectStore<{ x: number }>({ x: 3 }); 8 9function Counter() { 10 const count = useStore(counterStore, (s) => s.count); 11 return <div>count: {count}</div>; 12}
SimpleStore
(similar to Jotai atom)
1const store = createSimpleStore("Hello"); 2 3store.setState("Hello");
DeriveStore
(similar to Jotai derive atom, but work with stores too)
1const depStore1 = createObjectStore({ 2 value: [1], 3}); 4 5const depStore2 = createObjecStore({ 6 value: [2], 7}); 8 9// Working on removing the need to specify types of stores as the second type arg 10const deriveStore = derive<string, [typeof depStore1, typeof depStore2]>( 11 [depStore1, depStore2], 12 ([dep1, dep2], prevDeps, prevState) => { 13 return `${dep1} ${dep2}`; 14 } 15);
Middleware
1const store = subscribeWithSelector( 2 createObjectStore({ 3 x: [1], 4 y: "testing", 5 }) 6); 7 8// Select a slice (a property of the state) 9store.subscribe( 10 (state, prevState) => { 11 // ... 12 }, 13 (state) => state.y, 14 false // partial? 15); 16 17// Select a partial (subset of the state) 18store.subscribe( 19 (state, prevState) => { 20 // ... 21 }, 22 (state) => { 23 y: state.y; 24 }, 25 true // partial? 26); 27 28// Can be used as normal `subscribe` too 29store.subscribe((state, prevState) => { 30 // ... 31});
It seems like the majority of the complexity of Zustand comes from its middleware system. The challenge of creating such a middleware system is that the Store
(i.e. StoreApi
in Zustand terms) interface changes dynamically as middlewares are added to the store. For instance, when the subscribeWithSelector
middleware is added to the store, the subscribe
function takes a "selector" as an additional argument. In order to get type support for this behaviour, a lot of TS tricks are used.
This library's middleware system is facilited by JS Proxy. Each middleware must specify what Store
interface it can accept as the input. For instance, the subscribeWithSelector
middleware requires the input store to extends:
1export type ObjectStoreSubscribeListener<T> = (state: T, prevState: T) => void; 2 3export type ObjectStoreUnsubscriber = () => void; 4 5interface Store { 6 readonly setState: AnyFunction; 7 readonly getState: AnyFunction; 8 readonly subscribe: ( 9 listener: ObjectStoreSubscribeListener<T> 10 ) => ObjectStoreUnsubscriber; 11}
This is because the subscribeWithSelector
middleware will "hijack" the subscribe
function of the input store and hence it expects it to be in a particular form.
Middleware must also specify the type of the store after its mutation. For instance, the output type of the subscribeWithSelector
middleware will be:
1/** 2 * A type function that overwrites the properties of `T` with the properties of `U`. 3 */ 4type Overwrite<T, U> = Omit<T, keyof U> & U; 5 6type OutputStore = Overwrite< 7 InputStore, 8 { 9 /** 10 * A subscribe function with a selector function and a `partial` boolean field as additional arguments. 11 * @param listener A function that will be called when the subscribed state changes. 12 * @param selector A function that selects a slice or a partial of the state to subscribe to. 13 * @param partial A boolean field that indicates whether the selector function selects a partial of the state or a slice of the state. 14 * The field is used to determine how to equality checks should be performed, which in turn governs when the `listener` function will be triggered. 15 * - If `partial` is `false` or `undefined`, `Object.is` will be used to check for equality between states. 16 * - If `partial` is `true`, a 1-layer-deep `Object.is` will be used to check for equality between states. 17 * @returns void 18 */ 19 subscribe: CustomSubscribeFunction; 20 }
MIT
No vulnerabilities found.