|
1 | 1 | ## ❗️ In Development ❗️
|
2 | 2 |
|
3 |
| -The project is still in development. Hoping to release it right before Svelte 5 release. You can find usable examples in src/routes/+page.svelte. |
| 3 | +The project is still in development. Hoping to release it right before Svelte 5 release. You can find usable examples in `src/routes/+page.svelte`. |
4 | 4 |
|
5 | 5 | # katai
|
6 | 6 |
|
7 |
| -Kaṭai (meaning store in Tamil) is a simple and lightweight store for Svelte 5. |
| 7 | +Kaṭai (meaning store in Tamil) is a simple and lightweight store implementation for Svelte 5. |
8 | 8 |
|
9 |
| -It was based on top of the familiar APIs of Svelte 4 (and Svelte 3) stores while offering more functionality including adapters to easily cache the stores. |
| 9 | +The basics of Katai is a few primitives that can be used to build any type of store. You can also build the store type you need with the help of these primitives. We also provide a few pre-built variations to choose from the Stores options. Whichever feels the most suitable can be used. |
10 | 10 |
|
11 |
| -All while still being really small(less than 2kb gzipped including cache adapters). |
| 11 | +We do not wish to restrict you to a particular pattern for all your stores. You can copy the one of the current stores implementation as a base and build from on top it. |
12 | 12 |
|
13 |
| -[Was earlier called svelte-virtual-store] |
| 13 | +## Primitives |
14 | 14 |
|
15 |
| -## createStore |
| 15 | +### createStore |
16 | 16 |
|
17 |
| -The `createStore` function is used to create a new store. It takes two parameters: `store` and `mainStoreKey`. |
| 17 | +The function `createStore` creates a primitive store with a specified name and initial state. |
18 | 18 |
|
19 |
| -### Parameters |
| 19 | +- @param {string} storeName - The `storeName` parameter is a string that represents the name of the store being created. It is a required parameter for creating a new store. |
| 20 | +- @param {InferedState} storeState - The `storeState` parameter in the `createStore` function represents the initial state or value that will be stored in the created store. It is the data that the store will manage and provide access to. |
| 21 | +- @param {StoreOptions} [options] - The `options` parameter in the `createStore` function is an optional parameter that allows you to provide additional configuration options for creating the store. It is of type `StoreOptions`, which likely contains properties or settings that can be used to customize the behavior of the store creation process like adding cache adapters. |
| 22 | +- @returns A PrimitiveStore object with the store name and a getter function for the store value. |
20 | 23 |
|
21 |
| -- `store` (NewStore<T>): The store object to create the store from. |
22 |
| -- `config`: The config for the store. We can provide the cache options including the adapter. |
| 24 | +#### EXAMPLE |
23 | 25 |
|
24 |
| -### Return Value |
25 |
| - |
26 |
| -Returns a `Store` object with several methods to interact with the store's state, including `get`, `set`, `update`, `next`, and `has`. |
27 |
| - |
28 |
| -### Example |
29 |
| - |
30 |
| -```typescript |
31 |
| -import { createStore, idbAdapter } from 'katai'; |
32 |
| - |
33 |
| -type one = { |
34 |
| - name: 'test'; |
35 |
| - state: { |
36 |
| - foo: { |
37 |
| - bar: { |
38 |
| - baz: string; |
39 |
| - }; |
40 |
| - }; |
41 |
| - }; |
42 |
| -}; |
43 |
| - |
44 |
| -createStore( |
45 |
| - { |
46 |
| - name: 'test', |
47 |
| - state: { |
48 |
| - foo: { |
49 |
| - bar: { |
50 |
| - baz: 'heo' |
51 |
| - } |
52 |
| - } |
53 |
| - } |
54 |
| - } satisfies one, |
55 |
| - { |
56 |
| - cache: { |
57 |
| - adapter: idbAdapter |
58 |
| - } |
59 |
| - } |
60 |
| -); |
61 |
| -``` |
62 |
| - |
63 |
| -```typescript |
64 |
| -const test = store.get('check.one.two'); |
65 |
| - |
66 |
| -store.subscribe('check.one.two', (test) => { |
67 |
| - console.log('test - ', test); |
| 26 | +```ts |
| 27 | +export const counterCoreStore = createStore('test', { |
| 28 | + counter: 0 |
68 | 29 | });
|
69 |
| -``` |
70 |
| - |
71 |
| -Here typeof `test` will be `{ three: string; }` |
72 | 30 |
|
73 |
| -```typescript |
74 |
| -store.set('check.one.two.three', 0); |
| 31 | +// Returns |
| 32 | +PrimitiveStore<{ |
| 33 | + counter: number; |
| 34 | +}>; |
75 | 35 | ```
|
76 | 36 |
|
77 |
| -This will error as `Argument of type 'number' is not assignable to parameter of type 'string'.` |
| 37 | +### get |
78 | 38 |
|
79 |
| -You can subscribe to store changes for `a particular key` or for `deep changes`. When used inside `Svelte` component they will be `unSubscribed(auto-cleaned up)`. |
| 39 | +The `get` function takes a store and a derivation function, and returns a getter function that applies the derivation function to the store's value. |
80 | 40 |
|
81 |
| -```typescript |
82 |
| -store.subscribe('check.one.two', (test) => { |
83 |
| - console.log('test - ', test); |
84 |
| -}); |
85 |
| -// This will only run when two property of one object of check object changes |
86 |
| -``` |
| 41 | +- @param store - `PrimitiveStore<T>` is a generic type representing a store that holds a value of type `T`. It seems like the `store` parameter is expected to be an instance of this `PrimitiveStore` type. |
| 42 | +- @param derivation - The `derivation` parameter is a function that takes the current state of type `T` as input and returns a value of type `U`. It is used to derive a new value based on the current state stored in the `PrimitiveStore`. |
| 43 | +- @returns A `Getter<U>` function is being returned. This function takes no arguments and returns a value of type `U`. The value returned is the result of applying the `derivation` function to the `store.value`. |
87 | 44 |
|
88 |
| -If the value of a key is an POJO then will be able to subscribe deeply with `*` in the key. |
| 45 | +### update |
89 | 46 |
|
90 |
| -```typescript |
91 |
| -store.subscribe('check.one.*', (val) => { |
92 |
| - console.log('check.one.* - ', val); |
93 |
| -}); |
94 |
| -// This will run when any change is made to one object and it's children. |
95 |
| -``` |
| 47 | +The function `update` takes a store, a mutator function, and a payload, and updates the store's value using the mutator function while handling caching if applicable. |
96 | 48 |
|
97 |
| -This is not possible as the value of `three` is `string` |
| 49 | +- @param store - The `store` parameter is a PrimitiveStore object that holds a value of type T. |
| 50 | +- @param mutator - The `mutator` parameter is a function that takes the current state of the store (`T`) and a payload of type `C`, and returns a new state of type `U`. It is used to update the state of the store based on the provided payload. |
| 51 | +- @returns The `update` function returns an `Updater` function that takes a value of type `C` as an argument. |
98 | 52 |
|
99 |
| -```typescript |
100 |
| -// You will get the below error |
101 |
| -store.subscribe('check.one.two.three.*', (val) => { |
102 |
| - console.log('check.one.* - ', val); |
103 |
| -}); |
104 |
| -// Argument of type '"check.one.two.three.*"' is not assignable to parameter of type '"" | "check" | "check.*" | "check.one" | "check.one.*" | "check.one.two" | "check.one.two.*" | "check.one.two.three"' |
105 |
| -``` |
| 53 | +### subscribe |
106 | 54 |
|
107 |
| -## useStore Function |
| 55 | +The `subscribe` function allows for subscribing to a primitive store with specified subscribers and an effect to be executed. |
108 | 56 |
|
109 |
| -The `useStore` function is used to read and write data to the state of a store. |
| 57 | +- @param store - The `store` parameter is a PrimitiveStore that holds the state of type T. |
| 58 | +- @param subscribers - Subscribers are functions that subscribe to changes in the store's state. They are typically used to extract specific pieces of state from the store and react to changes in those pieces of state. |
| 59 | +- @param effect - The `effect` parameter in the `subscribe` function is a function that takes a `MapSources` object as its argument and performs some action based on the states provided in the `MapSources` object. |
| 60 | +- @returns The `subscribe` function returns a cleanup function that can be used to unsubscribe the effect and remove it from the list of subscribers. |
110 | 61 |
|
111 |
| -### Parameters |
| 62 | +#### EXAMPLE |
112 | 63 |
|
113 |
| -- `storeName` (string): The name of the store. |
| 64 | +```ts |
| 65 | +export const test = createStore('test', { |
| 66 | + counter: 0 |
| 67 | +}); |
114 | 68 |
|
115 |
| -### Return Value |
| 69 | +type StoreType = (typeof test)['value']; |
116 | 70 |
|
117 |
| -Returns a `StoreInstance` object with several methods to interact with the store's state, including `get`, `update`, `write`, `writeUpdate`, `next`, and `has`. |
| 71 | +export const testStore = { |
| 72 | + get $value() { |
| 73 | + return test.value; |
| 74 | + }, |
| 75 | + get: <U extends unknown>(derivation: (val: StoreType) => U) => get(test, () => derivation(test.value)), |
| 76 | + subscribe: <T extends Subscribers<StoreType>>(states: [...T], effect: (states: MapSources<T, StoreType>) => void) => |
| 77 | + subscribe(test, states, effect) |
| 78 | +}; |
118 | 79 |
|
119 |
| -### Example |
| 80 | +testStore.subscribe([(state) => state.counter], ([value]) => { |
| 81 | + console.log('counter', value); |
| 82 | +}); |
120 | 83 |
|
121 |
| -```typescript |
122 |
| -// Use an existing store |
123 |
| -const userStore = useStore<User>('users'); |
| 84 | +const interval = setInterval(() => { |
| 85 | + testStore.$value.counter = testStore.$value.counter + 1; |
| 86 | +}, 2000); |
124 | 87 |
|
125 |
| -// Use the store's methods |
126 |
| -userStore.get('username'); |
127 |
| -userStore.set('username', 'newUsername'); |
| 88 | +// cleanup |
| 89 | +onDestroy(() => { |
| 90 | + clearInterval(interval); |
| 91 | +}); |
128 | 92 | ```
|
129 | 93 |
|
130 |
| -## The `Store` object |
| 94 | +## Stores |
131 | 95 |
|
132 |
| -Returns a `storeObj` object with the following methods: |
| 96 | +### Basic Store |
133 | 97 |
|
134 |
| -- `get(key, defaultValue)`: Returns the value of the specified key in the store. |
135 |
| -- `set(key, value)`: Sets the value of the specified key. If the key does not exist, an error will be thrown. |
136 |
| -- `update(key, callback)`: Updates the value of the specified key using the provided callback function. |
137 |
| -- `next(callback, key)`: Calls the provided callback function with the value of the specified key. |
138 |
| -- `subscribe(key, subscriber)`: Adds a subscriber function to the specified key. |
139 |
| -- `unsubscribe(key, subscriber)`: Removes a subscriber function from the specified key. |
140 |
| -- `removeSubscribers(key)`: Removes all subscribers from the specified key. |
141 |
| -- `clearCache()`: Clears the cache of the store. |
142 |
| -- `dropStore()`: Deletes the specified store from the store. |
| 98 | +The function `createBasicStore` creates a basic store with state, getters, and actions based on the provided options. |
143 | 99 |
|
144 |
| -## Examples |
| 100 | +- @param {string} storeName - The `storeName` parameter is a string that represents the name of the store being created. |
| 101 | +- @param options - The `options` parameter in the `createBasicStore` function is an object that contains the following properties: |
| 102 | +- @param {StoreOptions} [settings] - The `settings` parameter in the `createBasicStore` function is an optional parameter of type `StoreOptions`. It allows you to provide additional settings or configurations for the store creation process. These settings can include options such as the store's persistence mechanism using cache adapters. |
| 103 | +- @returns The `createBasicStore` function returns an object of type `BasicStore<S, G, A>`, which includes the state, getters, actions, and additional methods like `clearCache` and `subscribe`. |
145 | 104 |
|
146 |
| -```javascript |
147 |
| -// Create a new store |
148 |
| -const myStore = createStore({ name: 'myStore', state: { myKey: 'value' } }); |
| 105 | +#### EXAMPLE |
149 | 106 |
|
150 |
| -// Add a subscriber to a key |
151 |
| -myStore.subscribe('myKey', (value, oldValue) => { |
152 |
| - console.log(`Value of myKey changed from ${oldValue} to ${value}`); |
| 107 | +```ts |
| 108 | +const newStore = createBasicStore('tester', { |
| 109 | + state: { |
| 110 | + counter: 0, |
| 111 | + count: 0 |
| 112 | + }, |
| 113 | + getters: { |
| 114 | + getCounter: (state) => state.counter, |
| 115 | + getCount: (state) => String(state.count) |
| 116 | + }, |
| 117 | + actions: { |
| 118 | + updateCounter: (state, payload: number) => { |
| 119 | + state.counter += payload; |
| 120 | + }, |
| 121 | + updateCount: (state, payload: number) => { |
| 122 | + state.count += payload; |
| 123 | + } |
| 124 | + } |
153 | 125 | });
|
154 | 126 |
|
155 |
| -// Set the value of a key |
156 |
| -myStore.set('myKey', 'newValue'); |
157 |
| - |
158 |
| -// Output: "Value of myKey changed from undefined to newValue" |
| 127 | +const interval = setInterval(() => { |
| 128 | + newStore.updateCounter(1); |
| 129 | +}, 2000); |
159 | 130 |
|
160 |
| -// Create a new store |
161 |
| -const userStore = createStore({ name: 'users', state: { username: 'value' } }); |
162 |
| - |
163 |
| -// Add a subscriber to a key |
164 |
| -userStore.subscribe('username', (value, oldValue) => { |
165 |
| - console.log(`Username changed from ${oldValue} to ${value}`); |
| 131 | +// cleanup |
| 132 | +onDestroy(() => { |
| 133 | + clearInterval(interval); |
166 | 134 | });
|
167 | 135 |
|
168 |
| -// Set the value of a key |
169 |
| -userStore.set('username', 'newUsername'); |
170 |
| - |
171 |
| -// Output: "Username changed from undefined to newUsername" |
172 |
| - |
173 |
| -// Update the value of a key |
174 |
| -userStore.update('username', (oldValue) => oldValue + '_updated'); |
175 |
| - |
176 |
| -// Output: "Username changed from newUsername to newUsername_updated" |
177 |
| - |
178 |
| -// Check if a key exists in the store |
179 |
| -console.log(userStore.has('username')); // Output: true |
180 |
| - |
181 |
| -// Get the value of a key |
182 |
| -console.log(userStore.get('username').value()); // Output: newUsername_updated |
| 136 | +newStore.subscribe([(state) => state.counter], (states) => { |
| 137 | + console.log('newStore', states[0]); |
| 138 | +}); |
| 139 | +``` |
183 | 140 |
|
184 |
| -// Remove a subscriber from a key |
185 |
| -userStore.unsubscribe('username', subscriberFunction); |
| 141 | +### Writable Store |
186 | 142 |
|
187 |
| -// Unsubscribe all subscribers from a key |
188 |
| -userStore.removeSubscribers('username'); |
| 143 | +The `createWritable` function creates a writable store with initial value and provides methods for getting, setting, updating, subscribing to changes, and clearing cache. |
189 | 144 |
|
190 |
| -// Drop a store |
191 |
| -userStore.dropStore(); |
192 |
| -``` |
| 145 | +- @param {T} initalValue - The `initalValue` parameter is the initial value that will be stored in the writable store. It should be an object of type `T`, which extends `Record<string, any>`. This initial value will be used as the starting value for the store. |
| 146 | +- @param storeName - The `storeName` parameter is a string that represents the name of the store where the data will be stored. If no `storeName` is provided, a random string will be generated for the store name. |
| 147 | +- @param {StoreOptions} [storeOptions] - The `storeOptions` parameter in the `createWritable` function is an optional parameter that allows you to specify additional options for the store creation. These options can include configuration settings or options specific to the underlying store implementation. If provided, these options will be used when creating the store using the `create |
| 148 | +- @returns An object is being returned with the following properties: |
| 149 | +- - get: a function that retrieves the current value from the store |
| 150 | +- - set: a function that updates the value in the store |
| 151 | +- - update: a function that takes a callback to update the value in the store |
| 152 | +- - subscribe: a function that subscribes to changes in the store and calls a subscriber function |
| 153 | +- - clearCache: a function that |
0 commit comments