yuustate 0.0.1 → 3.10.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.
- package/LICENSE +21 -0
- package/README.md +92 -3
- package/esm/index.d.mts +1 -0
- package/esm/index.mjs +1 -0
- package/esm/react/create-mutation.d.mts +143 -0
- package/esm/react/create-query.d.mts +519 -0
- package/esm/react/create-store.d.mts +35 -0
- package/esm/react/create-stores.d.mts +76 -0
- package/esm/react/create-stream.d.mts +343 -0
- package/esm/react/use-isomorphic-layout-effect.d.mts +6 -0
- package/esm/react/use-mutation.d.mts +84 -0
- package/esm/react/use-store.d.mts +34 -0
- package/esm/react.d.mts +8 -0
- package/esm/react.mjs +1031 -0
- package/esm/vanilla/basic.d.mts +13 -0
- package/esm/vanilla/hash.d.mts +7 -0
- package/esm/vanilla/store.d.mts +121 -0
- package/esm/vanilla.d.mts +3 -0
- package/esm/vanilla.mjs +90 -0
- package/index.d.ts +1 -0
- package/index.js +12 -0
- package/package.json +50 -3
- package/react/create-mutation.d.ts +143 -0
- package/react/create-query.d.ts +519 -0
- package/react/create-store.d.ts +35 -0
- package/react/create-stores.d.ts +76 -0
- package/react/create-stream.d.ts +343 -0
- package/react/use-isomorphic-layout-effect.d.ts +6 -0
- package/react/use-mutation.d.ts +84 -0
- package/react/use-store.d.ts +34 -0
- package/react.d.ts +8 -0
- package/react.js +1040 -0
- package/ts_version_4.5_and_above_is_required.d.ts +0 -0
- package/vanilla/basic.d.ts +13 -0
- package/vanilla/hash.d.ts +7 -0
- package/vanilla/store.d.ts +121 -0
- package/vanilla.d.ts +3 -0
- package/vanilla.js +97 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Muhammad Afifudin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -7,8 +7,97 @@ Inspired by [Zustand](https://zustand.docs.pmnd.rs) & [TanStack-Query](https://t
|
|
|
7
7
|
|
|
8
8
|
_Fine-grained reactivity, minimal boilerplate, zero dependencies._
|
|
9
9
|
|
|
10
|
+
Demo: https://afiiif.github.io/yuustate/
|
|
11
|
+
|
|
12
|
+
**Installation:**
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npm install yuustate
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Read the docs → https://yuustate.vercel.app**
|
|
19
|
+
|
|
20
|
+
<br>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
**Like Zustand, but has additional capabilities:**
|
|
25
|
+
- No selectors: automatically optimizes re-renders
|
|
26
|
+
- Store events: `onFirstSubscribe`, `onSubscribe`, `onUnsubscribe`, `onLastUnsubscribe`
|
|
27
|
+
- Easier to set initial state on SSR/SSG
|
|
28
|
+
- Smaller bundle
|
|
29
|
+
|
|
30
|
+
**Like TanStack Query, but:**
|
|
31
|
+
- DX is very similar to Zustand → One mental model for sync & async
|
|
32
|
+
- Much smaller bundle than TanStack Query → With nearly the same capabilities
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<br>
|
|
37
|
+
|
|
38
|
+
## Store (Global State)
|
|
39
|
+
|
|
40
|
+
A store is a global state container that can be used both **inside and outside** React.\
|
|
41
|
+
With YuuState, creating a store is simple:
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { createStore } from "yuustate/react";
|
|
45
|
+
|
|
46
|
+
const useLawn = createStore({
|
|
47
|
+
plants: 3,
|
|
48
|
+
zombies: 1,
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Use it inside a component:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
function MyPlants() {
|
|
56
|
+
const { plants } = useLawn(); // No selectors needed.
|
|
57
|
+
|
|
58
|
+
return <div>Plants: {plants}</div>; // Only re-render when plants state changes
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Update the state **anywhere**:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
const addPlant = () => {
|
|
66
|
+
useLawn.setState(prev => ({ plants: prev.plants + 1 }));
|
|
67
|
+
};
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Query Store for Async State
|
|
71
|
+
|
|
72
|
+
Create a query store for async data with `createQuery`:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
import { createQuery } from "yuustate/react";
|
|
76
|
+
|
|
77
|
+
const plantDetailQuery = createQuery(
|
|
78
|
+
async ({ id }) => {
|
|
79
|
+
const res = await fetch(`/api/plants/${id}`);
|
|
80
|
+
return res.json();
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use it in your component:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
function PlantDetail({ id }) {
|
|
89
|
+
const usePlantDetailQuery = plantDetailQuery({ id });
|
|
90
|
+
const { data, error } = usePlantDetailQuery();
|
|
91
|
+
|
|
92
|
+
if (!data && !error) return <div>Loading...</div>;
|
|
93
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
94
|
+
|
|
95
|
+
return <div>Name: {data.name}, damage: {data.damage}</div>;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
<br>
|
|
100
|
+
|
|
10
101
|
---
|
|
11
102
|
|
|
12
|
-
|
|
13
|
-
While the name has changed, the API and functionality remain the same.
|
|
14
|
-
Simply update your dependencies and imports to start using the new package.
|
|
103
|
+
Read the docs → https://yuustate.vercel.app
|
package/esm/index.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "yuustate/vanilla";
|
package/esm/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'yuustate/vanilla';
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { type InitStoreOptions, type SetStateInput } from "yuustate/vanilla";
|
|
2
|
+
/**
|
|
3
|
+
* Represents the state of a mutation.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* A mutation does not cache results and only tracks the latest execution.
|
|
7
|
+
*
|
|
8
|
+
* The state transitions are:
|
|
9
|
+
* - `INITIAL` → before any execution
|
|
10
|
+
* - `SUCCESS` → when mutation resolves successfully
|
|
11
|
+
* - `ERROR` → when mutation fails
|
|
12
|
+
*
|
|
13
|
+
* Unlike queries:
|
|
14
|
+
* - No retry mechanism
|
|
15
|
+
* - No caching across executions
|
|
16
|
+
*/
|
|
17
|
+
export type MutationState<TData, TVariable, TError> = {
|
|
18
|
+
isPending: boolean;
|
|
19
|
+
} & ({
|
|
20
|
+
state: "INITIAL";
|
|
21
|
+
isSuccess: false;
|
|
22
|
+
isError: false;
|
|
23
|
+
variable: undefined;
|
|
24
|
+
data: undefined;
|
|
25
|
+
dataUpdatedAt: undefined;
|
|
26
|
+
error: undefined;
|
|
27
|
+
errorUpdatedAt: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
state: "SUCCESS";
|
|
30
|
+
isSuccess: true;
|
|
31
|
+
isError: false;
|
|
32
|
+
variable: TVariable;
|
|
33
|
+
data: TData;
|
|
34
|
+
dataUpdatedAt: number;
|
|
35
|
+
error: undefined;
|
|
36
|
+
errorUpdatedAt: undefined;
|
|
37
|
+
} | {
|
|
38
|
+
state: "ERROR";
|
|
39
|
+
isSuccess: false;
|
|
40
|
+
isError: true;
|
|
41
|
+
variable: TVariable;
|
|
42
|
+
data: undefined;
|
|
43
|
+
dataUpdatedAt: undefined;
|
|
44
|
+
error: TError;
|
|
45
|
+
errorUpdatedAt: number;
|
|
46
|
+
});
|
|
47
|
+
export declare const INITIAL_STATE: MutationState<any, any, any>;
|
|
48
|
+
/**
|
|
49
|
+
* Configuration options for a mutation.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* Lifecycle callbacks are triggered for each execution.
|
|
53
|
+
*/
|
|
54
|
+
export type MutationOptions<TData, TVariable, TError = Error> = InitStoreOptions<MutationState<TData, TVariable, TError>> & {
|
|
55
|
+
/**
|
|
56
|
+
* Called when the mutation succeeds.\
|
|
57
|
+
* If multiple concurrent executions happened, only the latest execution triggers this callback.
|
|
58
|
+
*/
|
|
59
|
+
onSuccess?: (data: TData, variable: TVariable, stateBeforeExecute: MutationState<TData, TVariable, TError>) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Called when the mutation fails.\
|
|
62
|
+
* If multiple concurrent executions happened, only the latest execution triggers this callback.
|
|
63
|
+
*/
|
|
64
|
+
onError?: (error: TError, variable: TVariable, stateBeforeExecute: MutationState<TData, TVariable, TError>) => void;
|
|
65
|
+
/**
|
|
66
|
+
* Called after the mutation settles (either success or error).\
|
|
67
|
+
* If multiple concurrent executions happened, only the latest execution triggers this callback.
|
|
68
|
+
*/
|
|
69
|
+
onSettled?: (variable: TVariable, stateBeforeExecute: MutationState<TData, TVariable, TError>) => void;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Creates a mutation store for handling async operations that modify data.
|
|
73
|
+
*
|
|
74
|
+
* @param mutationFn - Async function that performs the mutation
|
|
75
|
+
* @param options - Optional configuration and lifecycle callbacks
|
|
76
|
+
*
|
|
77
|
+
* @returns A function that acts as both:
|
|
78
|
+
* - A React hook for subscribing to mutation state
|
|
79
|
+
* - A mutation controller (execute, reset, etc.)
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* - Mutations are **not cached** and only track the latest execution.
|
|
83
|
+
* - Designed for operations that change data (e.g. create, update, delete).
|
|
84
|
+
* - No retry mechanism is provided by default.
|
|
85
|
+
* - The mutation always resolves (never throws): the result contains either `data` or `error`.
|
|
86
|
+
* - If multiple executions triggered at the same time:
|
|
87
|
+
* - Only the latest execution is allowed to update the state.
|
|
88
|
+
* - Results from previous executions are ignored if a newer one exists.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* const useCreateUser = createMutation(async (input) => {
|
|
92
|
+
* return api.createUser(input);
|
|
93
|
+
* });
|
|
94
|
+
*
|
|
95
|
+
* const { isPending } = useCreateUser();
|
|
96
|
+
* const result = await useCreateUser.execute({ name: 'John' });
|
|
97
|
+
*
|
|
98
|
+
* @see https://yuustate.vercel.app/docs/mutation
|
|
99
|
+
*/
|
|
100
|
+
export declare const createMutation: <TData, TVariable = undefined, TError = Error>(mutationFn: (variable: TVariable, stateBeforeExecute: MutationState<TData, TVariable, TError>) => Promise<TData>, options?: MutationOptions<TData, TVariable, TError>) => (() => MutationState<TData, TVariable, TError>) & {
|
|
101
|
+
subscribe: (subscriber: import("../vanilla.d.mts").Subscriber<MutationState<TData, TVariable, TError>>) => () => void;
|
|
102
|
+
getSubscriberCount: () => number;
|
|
103
|
+
getState: () => MutationState<TData, TVariable, TError>;
|
|
104
|
+
/**
|
|
105
|
+
* Manually updates the mutation state.
|
|
106
|
+
*
|
|
107
|
+
* @remarks
|
|
108
|
+
* - Intended for advanced use cases.
|
|
109
|
+
* - Prefer using provided mutation actions (`execute`, `reset`) instead.
|
|
110
|
+
*/
|
|
111
|
+
setState: (value: SetStateInput<MutationState<TData, TVariable, TError>>) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Executes the mutation.
|
|
114
|
+
*
|
|
115
|
+
* @param variable - Input passed to the mutation function
|
|
116
|
+
*
|
|
117
|
+
* @returns A promise that always resolves with:
|
|
118
|
+
* - `{ data, variable }` on success
|
|
119
|
+
* - `{ error, variable }` on failure
|
|
120
|
+
*
|
|
121
|
+
* @remarks
|
|
122
|
+
* - The promise never rejects to simplify async handling.
|
|
123
|
+
* - If a mutation is already in progress, a warning is logged.
|
|
124
|
+
* - When a new execution starts, all previous pending executions will resolve with the result of the latest execution.
|
|
125
|
+
*/
|
|
126
|
+
execute: TVariable extends undefined ? () => Promise<{
|
|
127
|
+
variable: undefined;
|
|
128
|
+
data?: TData;
|
|
129
|
+
error?: TError;
|
|
130
|
+
}> : (variable: TVariable) => Promise<{
|
|
131
|
+
variable: TVariable;
|
|
132
|
+
data?: TData;
|
|
133
|
+
error?: TError;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Resets the mutation state back to its initial state.
|
|
137
|
+
*
|
|
138
|
+
* @remarks
|
|
139
|
+
* - Does not cancel any ongoing execution.
|
|
140
|
+
* - If an execution is still pending, its result may override the reset state.
|
|
141
|
+
*/
|
|
142
|
+
reset: () => void;
|
|
143
|
+
};
|