zustic 1.0.1 โ†’ 1.0.3

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/README.md CHANGED
@@ -1,42 +1,91 @@
1
- # Zustic
1
+ <div align="center">
2
2
 
3
- A lightweight, minimal state management library for React using `useSyncExternalStore`. Perfect for managing global state in React, React Native, and Next.js applications.
3
+ # ๐ŸŽฏ Zustic
4
4
 
5
- [![npm](https://img.shields.io/npm/v/zustic)](https://www.npmjs.com/package/zustic)
6
- [![license](https://img.shields.io/npm/l/zustic)](LICENSE)
7
- [![bundle size](https://img.shields.io/bundlephobia/minzip/zustic)](https://bundlephobia.com/package/zustic)
5
+ ### Lightweight State Management for Modern React Applications
8
6
 
9
- ## Features
7
+ [![npm version](https://img.shields.io/npm/v/zustic.svg)](https://npm.im/zustic)
8
+ [![npm downloads](https://img.shields.io/npm/dm/zustic.svg)](https://npm.im/zustic)
9
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/zustic)](https://bundlephobia.com/result?p=zustic)
10
+ [![License](https://img.shields.io/npm/l/zustic.svg)](LICENSE)
10
11
 
11
- โœจ **Lightweight** - Minimal footprint with zero dependencies (except React)
12
- โšก **Simple API** - Intuitive and easy to learn state management
13
- ๐ŸŽฃ **React Hooks** - Use hooks to access state in your components
14
- ๐Ÿ“ฑ **Multi-Platform** - Works with React, React Native, and Next.js
15
- ๐Ÿ”„ **Reactive Updates** - Automatic re-renders on state changes
16
- ๐Ÿ’พ **TypeScript Support** - Full TypeScript support with type safety
17
- ๐Ÿš€ **Production Ready** - Optimized for performance and reliability
12
+ A **fast, minimal state management solution** for React ecosystems. Works seamlessly with React, Next.js, and React Native with predictable state updates and a tiny footprint.
18
13
 
19
- ## Installation
14
+ [๐Ÿ“– Documentation](https://zustic.github.io/) ยท [๐Ÿ› Report Bug](https://github.com/DeveloperRejaul/zustic/issues) ยท [๐Ÿ’ก Request Feature](https://github.com/DeveloperRejaul/zustic/issues)
20
15
 
21
- ```bash
22
- npm install zustic
23
- ```
16
+ </div>
24
17
 
25
- or with yarn:
18
+ ---
26
19
 
27
- ```bash
28
- yarn add zustic
29
- ```
20
+ ## โœจ Key Features
21
+
22
+ ### Core Features
23
+ - **๐Ÿชถ Ultra-Lightweight** โ€” Only ~500B (gzipped) with zero dependencies
24
+ - **โšก Simple API** โ€” One function (`create`) to manage all your state
25
+ - **๐ŸŽฃ React Hooks** โ€” Native React hooks integration with automatic subscriptions
26
+ - **๐Ÿ“ฑ Multi-Platform** โ€” React, React Native, Next.js, and modern frameworks
27
+ - **๐Ÿ”„ Reactive Updates** โ€” Automatic re-renders with optimized batching
28
+ - **๐Ÿ’พ TypeScript First** โ€” Full type safety with perfect type inference
29
+ - **๐Ÿš€ Production Ready** โ€” Battle-tested in real applications
30
+
31
+ ### Advanced Capabilities
32
+ - **๐Ÿงฉ Middleware System** โ€” Extend functionality with logging, persistence, validation, and more
33
+ - **๐Ÿ“ก Direct State Access** โ€” `get()` function for reading state outside components
34
+ - **๐ŸŽฏ Selective Subscriptions** โ€” Components only re-render when their data changes
35
+ - **โš™๏ธ Fully Extensible** โ€” Build custom middleware for any use case
36
+ - **๐Ÿงช Easy Testing** โ€” Simple to test stores with middleware and async operations
37
+ - **๐Ÿ”— Framework Agnostic** โ€” Create middleware once, use everywhere
38
+
39
+ ---
40
+
41
+ ## ๐Ÿ“ฆ Installation
30
42
 
31
- or with pnpm:
43
+ Choose your favorite package manager:
32
44
 
33
45
  ```bash
46
+ # npm
47
+ npm install zustic
48
+
49
+ # yarn
50
+ yarn add zustic
51
+
52
+ # pnpm
34
53
  pnpm add zustic
35
54
  ```
36
55
 
37
- ## Quick Start
56
+ ---
57
+
58
+ ## ๐Ÿค” Why Zustic?
59
+
60
+ ### Size & Performance
61
+ | Metric | Zustic | Redux | Zustand | Context API |
62
+ |--------|--------|-------|---------|-------------|
63
+ | **Bundle Size** | ~500B | ~6KB | ~2KB | Built-in |
64
+ | **Performance** | โšก Optimized | Good | โšก Optimized | โš ๏ธ Re-renders |
65
+ | **Dependencies** | 0 | 0 | 0 | 0 |
66
+
67
+ ### Developer Experience
68
+ - **Ultra-Simple API**: Master everything in 5 minutes
69
+ - **Zero Boilerplate**: No actions, reducers, or providers
70
+ - **TypeScript Native**: Perfect type inference out of the box
71
+ - **Great DX**: Intuitive `create()`, `set()`, `get()` functions
72
+
73
+ ### Comparison with Other Libraries
74
+
75
+ | Feature | Zustic | Redux | Zustand | Context API |
76
+ |---------|--------|-------|---------|-------------|
77
+ | Bundle Size | ~500B โœ… | ~6KB | ~2KB | 0B |
78
+ | Learning Curve | โญ Easy | โญโญโญโญโญ Hard | โญโญ Easy | โญโญโญ Medium |
79
+ | Boilerplate | Minimal โœ… | Massive | Minimal | Some |
80
+ | TypeScript | Excellent โœ… | Good | Good | Good |
81
+ | Middleware | Built-in โœ… | Required | Optional | โŒ No |
82
+ | API Simplicity | Very Simple โœ… | Complex | Simple | Medium |
83
+
84
+ ---
38
85
 
39
- ### Basic Usage
86
+ ## ๐Ÿš€ Quick Start
87
+
88
+ ### 1. Create Your Store
40
89
 
41
90
  ```typescript
42
91
  import { create } from 'zustic';
@@ -56,7 +105,7 @@ export const useCounter = create<CounterStore>((set) => ({
56
105
  }));
57
106
  ```
58
107
 
59
- ### Using in React Components
108
+ ### 2. Use in Your Component
60
109
 
61
110
  ```typescript
62
111
  import { useCounter } from './store';
@@ -67,9 +116,9 @@ function Counter() {
67
116
  return (
68
117
  <div>
69
118
  <p>Count: {count}</p>
70
- <button onClick={inc}>Increment</button>
71
- <button onClick={dec}>Decrement</button>
72
- <button onClick={reset}>Reset</button>
119
+ <button onClick={inc}>โž• Increment</button>
120
+ <button onClick={dec}>โž– Decrement</button>
121
+ <button onClick={reset}>๐Ÿ”„ Reset</button>
73
122
  </div>
74
123
  );
75
124
  }
@@ -77,363 +126,354 @@ function Counter() {
77
126
  export default Counter;
78
127
  ```
79
128
 
80
- ## API Reference
129
+ That's it! No providers, no boilerplate, just pure state management.
81
130
 
82
- ### `create<T>(initializer)`
131
+ ---
83
132
 
84
- Creates a new store with the given state and actions.
133
+ ## ๐Ÿ“š Core Concepts
85
134
 
86
- #### Parameters
135
+ ### Create a Store
87
136
 
88
- - **initializer** `(set: (partial: Partial<T> | ((state: T) => Partial<T>)) => void) => T`
89
- - A function that receives the `set` function and returns the initial state object
90
- - The `set` function accepts either a partial state object or a function that takes the current state and returns a partial state object
137
+ The `create` function is the heart of Zustic:
91
138
 
92
- #### Returns
139
+ ```typescript
140
+ const useStore = create<StoreType>((set, get) => ({
141
+ // Your state and actions
142
+ }));
143
+ ```
93
144
 
94
- A React hook function that provides access to the store state.
145
+ - **`set`**: Update state (supports partial updates and functions)
146
+ - **`get`**: Read current state (works outside components)
95
147
 
96
- #### Type Parameters
148
+ ### Reading State in Components
97
149
 
98
- - **T** `extends object` - The shape of your store state
150
+ ```typescript
151
+ function Component() {
152
+ // Subscribe to entire store
153
+ const state = useStore();
154
+
155
+ // Or subscribe to specific properties (optimized)
156
+ const count = useStore((state) => state.count);
157
+
158
+ return <div>{count}</div>;
159
+ }
160
+ ```
161
+ <!--
162
+ ### Reading State Outside Components
99
163
 
100
- ## Advanced Examples
164
+ ```typescript
165
+ // In event handlers, callbacks, or services
166
+ const currentState = useStore.get();
167
+ console.log(currentState.count);
168
+ ```
101
169
 
102
- ### 1. Combining Multiple Stores
170
+ ### Updating State
103
171
 
104
172
  ```typescript
105
- import { create } from 'zustic';
173
+ // Partial update
174
+ useStore.set({ count: 5 });
106
175
 
107
- // User store
108
- export const useUserStore = create<UserStore>((set) => ({
109
- user: null,
110
- setUser: (user) => set({ user }),
111
- clearUser: () => set({ user: null }),
176
+ // Functional update with access to current state
177
+ useStore.set((state) => ({
178
+ count: state.count + 1
112
179
  }));
113
180
 
114
- // Todos store
115
- export const useTodosStore = create<TodosStore>((set) => ({
116
- todos: [],
117
- addTodo: (todo) => set((state) => ({
118
- todos: [...state.todos, todo]
119
- })),
120
- removeTodo: (id) => set((state) => ({
121
- todos: state.todos.filter(t => t.id !== id)
122
- })),
181
+ // Async updates
182
+ useStore.set(async (state) => ({
183
+ data: await fetchData(),
184
+ loading: false
123
185
  }));
186
+ ``` -->
124
187
 
125
- // Use both in a component
126
- function App() {
127
- const user = useUserStore();
128
- const todos = useTodosStore();
129
-
130
- return (
131
- <>
132
- <User />
133
- <TodoList />
134
- </>
135
- );
136
- }
137
- ```
188
+ ---
189
+
190
+ ## ๐Ÿงฉ Middleware System
191
+
192
+ Extend Zustic with powerful middleware for logging, persistence, validation, and more.
138
193
 
139
- ### 2. Complex State Updates
194
+ ### Logger Middleware
140
195
 
141
196
  ```typescript
142
- const useShopStore = create<ShopStore>((set) => ({
143
- items: [],
144
- cart: [],
145
- total: 0,
146
-
147
- addToCart: (item) => set((state) => ({
148
- cart: [...state.cart, item],
149
- total: state.total + item.price,
150
- })),
151
-
152
- removeFromCart: (itemId) => set((state) => ({
153
- cart: state.cart.filter(item => item.id !== itemId),
154
- total: state.total - state.cart.find(item => item.id === itemId)?.price || 0,
155
- })),
156
-
157
- clearCart: () => set({
158
- cart: [],
159
- total: 0,
197
+ const logger = <T extends object>(): Middleware<T> => (set, get) => (next) => async (partial) => {
198
+ console.log('๐Ÿ”ต Previous State:', get());
199
+ await next(partial);
200
+ console.log('๐ŸŸข New State:', get());
201
+ };
202
+
203
+ export const useStore = create<StoreType>(
204
+ (set) => ({
205
+ count: 0,
206
+ inc: () => set((state) => ({ count: state.count + 1 })),
160
207
  }),
161
- }));
208
+ [logger()]
209
+ );
162
210
  ```
163
211
 
164
- ### 3. Computed Values
212
+ ### Persistence Middleware
165
213
 
166
214
  ```typescript
167
- const useStatsStore = create<StatsStore>((set) => ({
168
- scores: [],
169
-
170
- addScore: (score) => set((state) => ({
171
- scores: [...state.scores, score],
172
- })),
173
-
174
- // You can compute values directly in the component
175
- // or create selector functions
176
- getAverage: (state) => {
177
- if (state.scores.length === 0) return 0;
178
- return state.scores.reduce((a, b) => a + b, 0) / state.scores.length;
179
- },
180
- }));
215
+ const persist = <T extends object>(): Middleware<T> => (set, get) => (next) => async (partial) => {
216
+ await next(partial);
217
+ localStorage.setItem('store', JSON.stringify(get()));
218
+ };
181
219
 
182
- function Stats() {
183
- const { scores, addScore, getAverage } = useStatsStore();
184
- const average = getAverage(useStatsStore());
185
-
186
- return <div>Average: {average}</div>;
187
- }
220
+ export const useStore = create<StoreType>(
221
+ (set) => ({
222
+ count: 0,
223
+ inc: () => set((state) => ({ count: state.count + 1 })),
224
+ }),
225
+ [persist()]
226
+ );
188
227
  ```
189
228
 
190
- ### 4. Next.js Usage
229
+ ### Validation Middleware
191
230
 
192
231
  ```typescript
193
- // store/counterStore.ts
194
- import { create } from 'zustic';
232
+ const validate = <T extends object>(): Middleware<T> => (set, get) => (next) => async (partial) => {
233
+ // Validate before updating
234
+ if (typeof partial === 'object' && partial.count < 0) {
235
+ console.warn('Invalid state update');
236
+ return;
237
+ }
238
+ await next(partial);
239
+ };
195
240
 
196
- export const useCounterStore = create<CounterStore>((set) => ({
197
- count: 0,
198
- increment: () => set((state) => ({ count: state.count + 1 })),
199
- decrement: () => set((state) => ({ count: state.count - 1 })),
200
- }));
241
+ export const useStore = create<StoreType>(
242
+ (set) => ({
243
+ count: 0,
244
+ inc: () => set((state) => ({ count: state.count + 1 })),
245
+ }),
246
+ [validate()]
247
+ );
201
248
  ```
202
249
 
250
+ ### Multiple Middleware
251
+
203
252
  ```typescript
204
- // app/page.tsx
205
- 'use client';
253
+ export const useStore = create<StoreType>(
254
+ (set) => ({
255
+ count: 0,
256
+ inc: () => set((state) => ({ count: state.count + 1 })),
257
+ }),
258
+ [logger(), persist(), validate()]
259
+ );
260
+ ```
261
+
262
+ ---
206
263
 
207
- import { useCounterStore } from '@/store/counterStore';
264
+ ## ๐Ÿ“ฑ Multi-Platform Examples
208
265
 
209
- export default function Home() {
210
- const { count, increment, decrement } = useCounterStore();
266
+ ### React Web
211
267
 
268
+ ```typescript
269
+ import { create } from 'zustic';
270
+
271
+ const useStore = create((set) => ({
272
+ count: 0,
273
+ inc: () => set((state) => ({ count: state.count + 1 })),
274
+ }));
275
+
276
+ export default function App() {
277
+ const { count, inc } = useStore();
212
278
  return (
213
- <main>
214
- <h1>Count: {count}</h1>
215
- <button onClick={increment}>+</button>
216
- <button onClick={decrement}>-</button>
217
- </main>
279
+ <div>
280
+ <p>{count}</p>
281
+ <button onClick={inc}>Increment</button>
282
+ </div>
218
283
  );
219
284
  }
220
285
  ```
221
286
 
222
- ### 5. React Native Usage
287
+ ### React Native
223
288
 
224
289
  ```typescript
225
290
  import { create } from 'zustic';
226
- import { View, Text, TouchableOpacity } from 'react-native';
291
+ import { View, Text, Button } from 'react-native';
227
292
 
228
- const useThemeStore = create<ThemeStore>((set) => ({
229
- isDark: false,
230
- toggleTheme: () => set((state) => ({ isDark: !state.isDark })),
293
+ const useStore = create((set) => ({
294
+ count: 0,
295
+ inc: () => set((state) => ({ count: state.count + 1 })),
231
296
  }));
232
297
 
233
- function App() {
234
- const { isDark, toggleTheme } = useThemeStore();
235
-
298
+ export default function App() {
299
+ const { count, inc } = useStore();
236
300
  return (
237
- <View style={{ backgroundColor: isDark ? '#000' : '#fff' }}>
238
- <Text>{isDark ? 'Dark Mode' : 'Light Mode'}</Text>
239
- <TouchableOpacity onPress={toggleTheme}>
240
- <Text>Toggle Theme</Text>
241
- </TouchableOpacity>
301
+ <View>
302
+ <Text>{count}</Text>
303
+ <Button title="Increment" onPress={inc} />
242
304
  </View>
243
305
  );
244
306
  }
245
307
  ```
246
308
 
247
- ## Best Practices
248
-
249
- ### 1. **Organize Stores**
250
- Keep your stores organized in a dedicated directory:
251
-
252
- ```
253
- src/
254
- โ”œโ”€โ”€ stores/
255
- โ”‚ โ”œโ”€โ”€ counterStore.ts
256
- โ”‚ โ”œโ”€โ”€ userStore.ts
257
- โ”‚ โ””โ”€โ”€ index.ts
258
- โ””โ”€โ”€ components/
259
- ```
260
-
261
- ### 2. **Type Your Store**
262
- Always define proper TypeScript types for better type safety:
309
+ ### Next.js
263
310
 
264
311
  ```typescript
265
- interface CounterState {
266
- count: number;
267
- inc: () => void;
268
- dec: () => void;
269
- }
312
+ 'use client';
270
313
 
271
- export const useCounter = create<CounterState>((set) => ({
314
+ import { create } from 'zustic';
315
+
316
+ const useStore = create((set) => ({
272
317
  count: 0,
273
318
  inc: () => set((state) => ({ count: state.count + 1 })),
274
- dec: () => set((state) => ({ count: state.count - 1 })),
275
319
  }));
276
- ```
277
320
 
278
- ### 3. **Keep State Flat**
279
- Try to keep your state structure as flat as possible for better performance:
321
+ export default function Page() {
322
+ const { count, inc } = useStore();
323
+ return (
324
+ <div>
325
+ <p>{count}</p>
326
+ <button onClick={inc}>Increment</button>
327
+ </div>
328
+ );
329
+ }
330
+ ```
280
331
 
281
- ```typescript
282
- // โŒ Avoid deeply nested structures
283
- const state = { user: { profile: { settings: { theme: 'dark' } } } };
332
+ ---
284
333
 
285
- // โœ… Prefer flat structures
286
- const state = { userTheme: 'dark' };
287
- ```
334
+ ## ๐Ÿงช Testing
288
335
 
289
- ### 4. **Use Immutable Updates**
290
- Always return new objects instead of mutating state:
336
+ Zustic stores are easy to test:
291
337
 
292
338
  ```typescript
293
- // โŒ Bad - mutating state
294
- set((state) => {
295
- state.items.push(newItem);
296
- return state;
297
- });
339
+ import { create } from 'zustic';
298
340
 
299
- // โœ… Good - immutable updates
300
- set((state) => ({
301
- items: [...state.items, newItem],
341
+ // Your store
342
+ const useStore = create((set) => ({
343
+ count: 0,
344
+ inc: () => set((state) => ({ count: state.count + 1 })),
345
+ reset: () => set({ count: 0 }),
302
346
  }));
303
- ```
304
-
305
- ## Performance Tips
306
347
 
307
- 1. **Minimize Subscriptions** - Only subscribe to the parts of the state you need
308
- 2. **Use Memoization** - Memoize components that depend on store state
309
- 3. **Avoid Large Objects** - Split large stores into multiple smaller ones
310
- 4. **Batch Updates** - Group related state updates together
348
+ // Test it
349
+ describe('Counter Store', () => {
350
+ it('should increment count', () => {
351
+ useStore.set({ count: 0 });
352
+ useStore.get().inc();
353
+ expect(useStore.get().count).toBe(1);
354
+ });
355
+
356
+ it('should reset count', () => {
357
+ useStore.set({ count: 5 });
358
+ useStore.get().reset();
359
+ expect(useStore.get().count).toBe(0);
360
+ });
361
+ });
362
+ ```
311
363
 
312
- ## Browser Support
364
+ ---
313
365
 
314
- Zustic works in all modern browsers that support ES6 and React 16.8+.
366
+ ## ๐Ÿ’ก Advanced Examples
315
367
 
316
- - Chrome/Edge (latest)
317
- - Firefox (latest)
318
- - Safari (latest)
319
- - Mobile browsers supporting React Native
368
+ ### Async State
320
369
 
321
- ## Comparison
370
+ ```typescript
371
+ const useUserStore = create((set, get) => ({
372
+ user: null,
373
+ loading: false,
374
+ error: null,
375
+
376
+ fetchUser: async (id: string) => {
377
+ set({ loading: true });
378
+ try {
379
+ const response = await fetch(`/api/users/${id}`);
380
+ const user = await response.json();
381
+ set({ user, loading: false, error: null });
382
+ } catch (error) {
383
+ set({ error: error.message, loading: false });
384
+ }
385
+ },
386
+ }));
387
+ ```
322
388
 
323
- | Feature | Zustic | Zustand | Redux | Context API |
324
- |---------|--------|---------|-------|-------------|
325
- | Bundle Size | ~500B | ~2KB | ~7KB | - |
326
- | Learning Curve | Very Easy | Easy | Hard | Medium |
327
- | Boilerplate | Minimal | Minimal | Lots | Medium |
328
- | DevTools | No | Yes | Yes | No |
329
- | Middleware | No | Yes | Yes | No |
330
- | TypeScript | โœ… | โœ… | โœ… | โœ… |
389
+ ### Computed State
331
390
 
332
- ## Troubleshooting
391
+ ```typescript
392
+ const useCartStore = create((set, get) => ({
393
+ items: [],
394
+
395
+ addItem: (item) => set((state) => ({
396
+ items: [...state.items, item],
397
+ })),
398
+
399
+ get total() {
400
+ return get().items.reduce((sum, item) => sum + item.price, 0);
401
+ },
402
+ }));
403
+ ```
333
404
 
334
- ### State not updating?
335
- Make sure you're using the `set` function correctly. Always return a new object:
405
+ ### Nested Stores
336
406
 
337
407
  ```typescript
338
- // โŒ Wrong
339
- set({ count: state.count + 1 }); // state is undefined here
408
+ const useAuthStore = create((set) => ({
409
+ user: null,
410
+ login: (user) => set({ user }),
411
+ logout: () => set({ user: null }),
412
+ }));
340
413
 
341
- // โœ… Correct
342
- set((state) => ({ count: state.count + 1 }));
414
+ const useAppStore = create((set) => ({
415
+ auth: useAuthStore,
416
+ theme: 'light',
417
+ }));
343
418
  ```
344
419
 
345
- ### Component not re-rendering?
346
- Ensure you're using the hook at the top level of your component:
420
+ ---
347
421
 
348
- ```typescript
349
- // โŒ Bad
350
- if (condition) {
351
- const state = useStore();
352
- }
422
+ ## ๐Ÿ”— Resources
353
423
 
354
- // โœ… Good
355
- const state = useStore();
356
- ```
424
+ - ๐Ÿ“– **[Full Documentation](https://zustic.github.io/)** - Complete API reference and guides
425
+ - ๐Ÿ› **[GitHub Issues](https://github.com/DeveloperRejaul/zustic/issues)** - Report bugs and request features
426
+ - ๐Ÿ’ฌ **[Discussions](https://github.com/DeveloperRejaul/zustic/discussions)** - Ask questions and share ideas
427
+ - ๐Ÿ“ฆ **[NPM Package](https://npm.im/zustic)** - Install and view package info
357
428
 
358
- ## Migration Guide
429
+ ---
359
430
 
360
- ### From Context API
431
+ ## ๐Ÿ“ API Reference
361
432
 
362
- Before:
363
- ```typescript
364
- const CounterContext = createContext();
433
+ ### `create<T>(initializer, middlewares?)`
365
434
 
366
- export function CounterProvider({ children }) {
367
- const [count, setCount] = useState(0);
368
-
369
- return (
370
- <CounterContext.Provider value={{ count, setCount }}>
371
- {children}
372
- </CounterContext.Provider>
373
- );
374
- }
435
+ Creates a new store with state and actions.
375
436
 
376
- function useCounter() {
377
- return useContext(CounterContext);
378
- }
379
- ```
437
+ **Parameters:**
438
+ - `initializer` - Function that receives `set` and `get`, returns initial state
439
+ - `middlewares` (optional) - Array of middleware functions
440
+
441
+ **Returns:**
442
+ - A hook function that provides access to store state and actions
380
443
 
381
- After:
444
+ **Example:**
382
445
  ```typescript
383
- export const useCounter = create((set) => ({
384
- count: 0,
385
- setCount: (count) => set({ count }),
446
+ const useStore = create((set, get) => ({
447
+ value: 0,
448
+ increment: () => set((state) => ({ value: state.value + 1 })),
449
+ getValue: () => get().value,
386
450
  }));
387
451
  ```
388
452
 
389
- ### From Redux
453
+ ---
390
454
 
391
- Before:
392
- ```typescript
393
- const counterSlice = createSlice({
394
- name: 'counter',
395
- initialState: { count: 0 },
396
- reducers: {
397
- increment: (state) => { state.count += 1; },
398
- },
399
- });
455
+ ## ๐Ÿค Contributing
400
456
 
401
- export const { increment } = counterSlice.actions;
402
- export default useSelector((state) => state.counter);
403
- ```
457
+ Contributions are welcome! Please feel free to submit a Pull Request to the [GitHub repository](https://github.com/DeveloperRejaul/zustic).
404
458
 
405
- After:
406
- ```typescript
407
- export const useCounter = create((set) => ({
408
- count: 0,
409
- increment: () => set((state) => ({ count: state.count + 1 })),
410
- }));
411
- ```
459
+ ---
412
460
 
413
- ## Contributing
461
+ ## ๐Ÿ“„ License
414
462
 
415
- Contributions are welcome! Please feel free to submit a Pull Request.
463
+ MIT License ยฉ 2024 [Rejaul Karim](https://github.com/DeveloperRejaul)
416
464
 
417
- ## License
465
+ ---
418
466
 
419
- ISC ยฉ 2024 [Rejaul Karim](https://github.com/DeveloperRejaul)
467
+ ## ๐Ÿ‘จโ€๐Ÿ’ป Author
420
468
 
421
- ## Support
469
+ Created by **Rejaul Karim** - [GitHub](https://github.com/DeveloperRejaul)
422
470
 
423
- - ๐Ÿ“– [Documentation](https://github.com/DeveloperRejaul/zustic)
424
- - ๐Ÿ› [Bug Reports](https://github.com/DeveloperRejaul/zustic/issues)
425
- - ๐Ÿ’ฌ [Discussions](https://github.com/DeveloperRejaul/zustic/discussions)
471
+ ---
426
472
 
427
- ## Related Projects
473
+ <div align="center">
428
474
 
429
- - [Zustand](https://github.com/pmndrs/zustand) - A small, fast and scalable bearbones state-management solution
430
- - [Jotai](https://github.com/pmndrs/jotai) - Primitive and flexible state management for React
431
- - [Recoil](https://recoiljs.org/) - A state management library for React
475
+ ### Made with โค๏ธ for the React community
432
476
 
433
- ## Changelog
477
+ โญ Star us on [GitHub](https://github.com/DeveloperRejaul/zustic) if you find this helpful!
434
478
 
435
- ### v1.0.0 (2026)
436
- - Initial release
437
- - Basic state management with `create` function
438
- - TypeScript support
439
- - React, React Native, and Next.js compatibility
479
+ </div>
@@ -0,0 +1 @@
1
+ import{useSyncExternalStore as p}from"react";function d(a,n=[]){let e,t=[],s=r=>{let o=typeof r=="function"?r(e):r;e={...e,...o},t.forEach(T=>T())},i=()=>e,c=l(s,i,n);e=a(c,i);let S=r=>(t.push(r),()=>{t=t.filter(o=>o!==r)});return()=>p(S,i)}var l=(a,n,e)=>!e||e.length===0?a:e.reduceRight((t,s)=>s(a,n)(t),a);export{d as a};
package/dist/index.js CHANGED
@@ -1,73 +1 @@
1
- "use strict";
2
- "use client";
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
- var __spreadValues = (a, b) => {
11
- for (var prop in b || (b = {}))
12
- if (__hasOwnProp.call(b, prop))
13
- __defNormalProp(a, prop, b[prop]);
14
- if (__getOwnPropSymbols)
15
- for (var prop of __getOwnPropSymbols(b)) {
16
- if (__propIsEnum.call(b, prop))
17
- __defNormalProp(a, prop, b[prop]);
18
- }
19
- return a;
20
- };
21
- var __export = (target, all) => {
22
- for (var name in all)
23
- __defProp(target, name, { get: all[name], enumerable: true });
24
- };
25
- var __copyProps = (to, from, except, desc) => {
26
- if (from && typeof from === "object" || typeof from === "function") {
27
- for (let key of __getOwnPropNames(from))
28
- if (!__hasOwnProp.call(to, key) && key !== except)
29
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
30
- }
31
- return to;
32
- };
33
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
34
-
35
- // src/index.ts
36
- var index_exports = {};
37
- __export(index_exports, {
38
- create: () => create
39
- });
40
- module.exports = __toCommonJS(index_exports);
41
- var import_react = require("react");
42
- function create(initializer, middlewares = []) {
43
- let state;
44
- let listeners = [];
45
- const setState = (partial) => {
46
- const partialState = typeof partial === "function" ? partial(state) : partial;
47
- state = __spreadValues(__spreadValues({}, state), partialState);
48
- listeners.forEach((l) => l());
49
- };
50
- const getState = () => state;
51
- const setStateWithMiddleware = applyMiddleware(setState, getState, middlewares);
52
- state = initializer(setStateWithMiddleware, getState);
53
- const subscribe = (listener) => {
54
- listeners.push(listener);
55
- return () => {
56
- listeners = listeners.filter((l) => l !== listener);
57
- };
58
- };
59
- return () => (0, import_react.useSyncExternalStore)(subscribe, getState);
60
- }
61
- var applyMiddleware = (set, get, middlewares) => {
62
- if (!middlewares || middlewares.length === 0) {
63
- return set;
64
- }
65
- return middlewares.reduceRight(
66
- (next, mw) => mw(set, get)(next),
67
- set
68
- );
69
- };
70
- // Annotate the CommonJS export names for ESM import in node:
71
- 0 && (module.exports = {
72
- create
73
- });
1
+ "use strict";var c=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var y=(t,r)=>{for(var e in r)c(t,e,{get:r[e],enumerable:!0})},M=(t,r,e,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of f(r))!m.call(t,o)&&o!==e&&c(t,o,{get:()=>r[o],enumerable:!(a=u(r,o))||a.enumerable});return t};var P=t=>M(c({},"__esModule",{value:!0}),t);var x={};y(x,{create:()=>S});module.exports=P(x);var p=require("react");function S(t,r=[]){let e,a=[],o=s=>{let i=typeof s=="function"?s(e):s;e={...e,...i},a.forEach(l=>l())},n=()=>e,T=h(o,n,r);e=t(T,n);let d=s=>(a.push(s),()=>{a=a.filter(i=>i!==s)});return()=>(0,p.useSyncExternalStore)(d,n)}var h=(t,r,e)=>!e||e.length===0?t:e.reduceRight((a,o)=>o(t,r)(a),t);0&&(module.exports={create});
package/dist/index.mjs CHANGED
@@ -1,51 +1 @@
1
- "use client";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
6
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
- var __spreadValues = (a, b) => {
8
- for (var prop in b || (b = {}))
9
- if (__hasOwnProp.call(b, prop))
10
- __defNormalProp(a, prop, b[prop]);
11
- if (__getOwnPropSymbols)
12
- for (var prop of __getOwnPropSymbols(b)) {
13
- if (__propIsEnum.call(b, prop))
14
- __defNormalProp(a, prop, b[prop]);
15
- }
16
- return a;
17
- };
18
-
19
- // src/index.ts
20
- import { useSyncExternalStore } from "react";
21
- function create(initializer, middlewares = []) {
22
- let state;
23
- let listeners = [];
24
- const setState = (partial) => {
25
- const partialState = typeof partial === "function" ? partial(state) : partial;
26
- state = __spreadValues(__spreadValues({}, state), partialState);
27
- listeners.forEach((l) => l());
28
- };
29
- const getState = () => state;
30
- const setStateWithMiddleware = applyMiddleware(setState, getState, middlewares);
31
- state = initializer(setStateWithMiddleware, getState);
32
- const subscribe = (listener) => {
33
- listeners.push(listener);
34
- return () => {
35
- listeners = listeners.filter((l) => l !== listener);
36
- };
37
- };
38
- return () => useSyncExternalStore(subscribe, getState);
39
- }
40
- var applyMiddleware = (set, get, middlewares) => {
41
- if (!middlewares || middlewares.length === 0) {
42
- return set;
43
- }
44
- return middlewares.reduceRight(
45
- (next, mw) => mw(set, get)(next),
46
- set
47
- );
48
- };
49
- export {
50
- create
51
- };
1
+ import{a as e}from"./chunk-SISWF3T4.mjs";export{e as create};
@@ -0,0 +1,116 @@
1
+ type QueryFnObj = {
2
+ url: string;
3
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
4
+ body?: any;
5
+ headers?: Record<string, any>;
6
+ };
7
+ type QueryFnReturn = string | QueryFnObj;
8
+ type QueryFn<Arg = any> = (arg: Arg) => QueryFnReturn;
9
+ type MainQueryReturnTypes = Promise<{
10
+ data: any;
11
+ error?: undefined;
12
+ } | {
13
+ error: any;
14
+ data?: undefined;
15
+ }>;
16
+ type ApiOption<Arg, R> = {
17
+ transformResponse?: (currData: any, preData: any) => Promise<R> | R;
18
+ transformError?: (currError: any, preError: any) => Promise<any> | any;
19
+ transformBody?: (body: Arg) => Promise<any> | any;
20
+ transformHeader?: (header: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>;
21
+ onError?: (err: any) => Promise<void> | void;
22
+ onSuccess?: (data: R) => Promise<void> | void;
23
+ queryFnc?: (arg: Arg, baseQuery: CreateApiParams<any>['baseQuery']) => MainQueryReturnTypes;
24
+ middlewares?: ApiMiddleware[];
25
+ plugins?: ApiPlugin[];
26
+ };
27
+ type QueryDef<Arg, Result> = {
28
+ type: 'query';
29
+ queryFn?: QueryFn<Arg>;
30
+ } & ApiOption<Arg, Result>;
31
+ type MutationDef<Arg, Result> = {
32
+ type: 'mutation';
33
+ queryFn?: QueryFn<Arg>;
34
+ } & ApiOption<Arg, Result>;
35
+ type EndpointDef = QueryDef<any, any> | MutationDef<any, any>;
36
+ type MainQueryHookResult<Result> = {
37
+ data?: Result;
38
+ isLoading: boolean;
39
+ isError: boolean;
40
+ isFetching: boolean;
41
+ isSuccess: boolean;
42
+ error: any;
43
+ reFetch: () => MainQueryReturnTypes;
44
+ };
45
+ type MainMutationState<Result> = {
46
+ data?: Result;
47
+ isLoading: boolean;
48
+ isError: boolean;
49
+ isSuccess: boolean;
50
+ error: any;
51
+ };
52
+ type EndpointsMap = Record<string, EndpointDef>;
53
+ type HooksFromEndpoints<T extends EndpointsMap> = {
54
+ [K in keyof T as T[K] extends {
55
+ type: 'query';
56
+ } ? `use${Capitalize<string & K>}Query` : `use${Capitalize<string & K>}Mutation`]: T[K] extends QueryDef<infer Arg, infer Result> ? (arg: Arg, option?: QueryHookOption) => MainQueryHookResult<Result> : T[K] extends MutationDef<infer Arg, infer Result> ? () => readonly [(arg: Arg) => Promise<Result>, MainMutationState<Result>] : never;
57
+ };
58
+ type BuilderType = {
59
+ query<Result, Arg = void>(config: {
60
+ query?: (arg: Arg) => QueryFnReturn;
61
+ } & ApiOption<Arg, Result>): QueryDef<Arg, Result>;
62
+ mutation<Result, Arg = void>(config: {
63
+ query?: (arg: Arg) => QueryFnObj;
64
+ } & ApiOption<Arg, Result>): MutationDef<Arg, Result>;
65
+ };
66
+ type BaseQueryReturn<Data = any, Error = any> = {
67
+ data: Data;
68
+ error?: undefined;
69
+ } | {
70
+ data?: undefined;
71
+ error: Error;
72
+ };
73
+ interface CreateApiParams<T extends EndpointsMap> {
74
+ baseQuery: (option: QueryFnReturn) => Promise<BaseQueryReturn>;
75
+ endpoints: (builder: BuilderType) => T;
76
+ clashTimeout?: number;
77
+ middlewares?: ApiMiddleware[];
78
+ plugins?: ApiPlugin[];
79
+ }
80
+ interface QueryHookOption {
81
+ skip: boolean;
82
+ }
83
+ type MiddlewareContext = {
84
+ arg: any;
85
+ def: any;
86
+ get: any;
87
+ set: any;
88
+ };
89
+ type ApiMiddleware = (ctx: MiddlewareContext, next: () => Promise<{
90
+ data?: any;
91
+ error?: any;
92
+ }>) => Promise<{
93
+ data?: any;
94
+ error?: any;
95
+ }>;
96
+ type ApiPlugin = {
97
+ name: string;
98
+ onInit?: (api: {
99
+ baseQuery: any;
100
+ endpoints: any;
101
+ }) => void;
102
+ beforeQuery?: (ctx: PluginContext) => void | Promise<void>;
103
+ middleware?: ApiMiddleware;
104
+ afterQuery?: (result: any, ctx: PluginContext) => void | Promise<void>;
105
+ onError?: (error: any, ctx: PluginContext) => void | Promise<void>;
106
+ };
107
+ type PluginContext = {
108
+ arg: any;
109
+ def: any;
110
+ get: any;
111
+ set: any;
112
+ };
113
+
114
+ declare function createApi<T extends EndpointsMap>(params: CreateApiParams<T>): HooksFromEndpoints<T>;
115
+
116
+ export { type ApiMiddleware, type ApiPlugin, createApi };
@@ -0,0 +1,116 @@
1
+ type QueryFnObj = {
2
+ url: string;
3
+ method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
4
+ body?: any;
5
+ headers?: Record<string, any>;
6
+ };
7
+ type QueryFnReturn = string | QueryFnObj;
8
+ type QueryFn<Arg = any> = (arg: Arg) => QueryFnReturn;
9
+ type MainQueryReturnTypes = Promise<{
10
+ data: any;
11
+ error?: undefined;
12
+ } | {
13
+ error: any;
14
+ data?: undefined;
15
+ }>;
16
+ type ApiOption<Arg, R> = {
17
+ transformResponse?: (currData: any, preData: any) => Promise<R> | R;
18
+ transformError?: (currError: any, preError: any) => Promise<any> | any;
19
+ transformBody?: (body: Arg) => Promise<any> | any;
20
+ transformHeader?: (header: Record<string, any>) => Promise<Record<string, any>> | Record<string, any>;
21
+ onError?: (err: any) => Promise<void> | void;
22
+ onSuccess?: (data: R) => Promise<void> | void;
23
+ queryFnc?: (arg: Arg, baseQuery: CreateApiParams<any>['baseQuery']) => MainQueryReturnTypes;
24
+ middlewares?: ApiMiddleware[];
25
+ plugins?: ApiPlugin[];
26
+ };
27
+ type QueryDef<Arg, Result> = {
28
+ type: 'query';
29
+ queryFn?: QueryFn<Arg>;
30
+ } & ApiOption<Arg, Result>;
31
+ type MutationDef<Arg, Result> = {
32
+ type: 'mutation';
33
+ queryFn?: QueryFn<Arg>;
34
+ } & ApiOption<Arg, Result>;
35
+ type EndpointDef = QueryDef<any, any> | MutationDef<any, any>;
36
+ type MainQueryHookResult<Result> = {
37
+ data?: Result;
38
+ isLoading: boolean;
39
+ isError: boolean;
40
+ isFetching: boolean;
41
+ isSuccess: boolean;
42
+ error: any;
43
+ reFetch: () => MainQueryReturnTypes;
44
+ };
45
+ type MainMutationState<Result> = {
46
+ data?: Result;
47
+ isLoading: boolean;
48
+ isError: boolean;
49
+ isSuccess: boolean;
50
+ error: any;
51
+ };
52
+ type EndpointsMap = Record<string, EndpointDef>;
53
+ type HooksFromEndpoints<T extends EndpointsMap> = {
54
+ [K in keyof T as T[K] extends {
55
+ type: 'query';
56
+ } ? `use${Capitalize<string & K>}Query` : `use${Capitalize<string & K>}Mutation`]: T[K] extends QueryDef<infer Arg, infer Result> ? (arg: Arg, option?: QueryHookOption) => MainQueryHookResult<Result> : T[K] extends MutationDef<infer Arg, infer Result> ? () => readonly [(arg: Arg) => Promise<Result>, MainMutationState<Result>] : never;
57
+ };
58
+ type BuilderType = {
59
+ query<Result, Arg = void>(config: {
60
+ query?: (arg: Arg) => QueryFnReturn;
61
+ } & ApiOption<Arg, Result>): QueryDef<Arg, Result>;
62
+ mutation<Result, Arg = void>(config: {
63
+ query?: (arg: Arg) => QueryFnObj;
64
+ } & ApiOption<Arg, Result>): MutationDef<Arg, Result>;
65
+ };
66
+ type BaseQueryReturn<Data = any, Error = any> = {
67
+ data: Data;
68
+ error?: undefined;
69
+ } | {
70
+ data?: undefined;
71
+ error: Error;
72
+ };
73
+ interface CreateApiParams<T extends EndpointsMap> {
74
+ baseQuery: (option: QueryFnReturn) => Promise<BaseQueryReturn>;
75
+ endpoints: (builder: BuilderType) => T;
76
+ clashTimeout?: number;
77
+ middlewares?: ApiMiddleware[];
78
+ plugins?: ApiPlugin[];
79
+ }
80
+ interface QueryHookOption {
81
+ skip: boolean;
82
+ }
83
+ type MiddlewareContext = {
84
+ arg: any;
85
+ def: any;
86
+ get: any;
87
+ set: any;
88
+ };
89
+ type ApiMiddleware = (ctx: MiddlewareContext, next: () => Promise<{
90
+ data?: any;
91
+ error?: any;
92
+ }>) => Promise<{
93
+ data?: any;
94
+ error?: any;
95
+ }>;
96
+ type ApiPlugin = {
97
+ name: string;
98
+ onInit?: (api: {
99
+ baseQuery: any;
100
+ endpoints: any;
101
+ }) => void;
102
+ beforeQuery?: (ctx: PluginContext) => void | Promise<void>;
103
+ middleware?: ApiMiddleware;
104
+ afterQuery?: (result: any, ctx: PluginContext) => void | Promise<void>;
105
+ onError?: (error: any, ctx: PluginContext) => void | Promise<void>;
106
+ };
107
+ type PluginContext = {
108
+ arg: any;
109
+ def: any;
110
+ get: any;
111
+ set: any;
112
+ };
113
+
114
+ declare function createApi<T extends EndpointsMap>(params: CreateApiParams<T>): HooksFromEndpoints<T>;
115
+
116
+ export { type ApiMiddleware, type ApiPlugin, createApi };
@@ -0,0 +1 @@
1
+ "use strict";var M=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var C=(t,n)=>{for(var a in n)M(t,a,{get:n[a],enumerable:!0})},R=(t,n,a,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let u of k(n))!H.call(t,u)&&u!==a&&M(t,u,{get:()=>n[u],enumerable:!(r=L(n,u))||r.enumerable});return t};var O=t=>R(M({},"__esModule",{value:!0}),t);var D={};C(D,{createApi:()=>N});module.exports=O(D);var A=require("react");var P=require("react");function g(t,n=[]){let a,r=[],u=c=>{let i=typeof c=="function"?c(a):c;a={...a,...i},r.forEach(y=>y())},w=()=>a,F=B(u,w,n);a=t(F,w);let S=c=>(r.push(c),()=>{r=r.filter(i=>i!==c)});return()=>(0,P.useSyncExternalStore)(S,w)}var B=(t,n,a)=>!a||a.length===0?t:a.reduceRight((r,u)=>u(t,n)(r),t);function v(t){return t.charAt(0).toUpperCase()+t.slice(1)}var J=async(t,n,a,r,u,w,F)=>{var S,c,i,y,T,m,p;n({isLoading:!0});try{let e=null,o=null,s=a().cashExp,b=Date.now(),h=!1;if(F||JSON.stringify(a().arg||{})!==JSON.stringify(t||{})?h=!1:h=s>=b,h&&(e=a().data),!h&&(r!=null&&r.queryFnc)){n({isFetching:!0});let{data:l,error:E}=await((S=r==null?void 0:r.queryFnc)==null?void 0:S.call(r,t,u));l&&(e=l),E&&(o=E)}else{let l=r.queryFn(t);if(r!=null&&r.transformHeader&&(l.headers=await((c=r==null?void 0:r.transformHeader)==null?void 0:c.call(r,l==null?void 0:l.headers))),r!=null&&r.transformBody&&(l.body=await((i=r==null?void 0:r.transformBody)==null?void 0:i.call(r,l==null?void 0:l.body))),!h){n({isFetching:!0});let{data:E,error:q}=await u(l);E&&(e=E),q&&(o=q)}}return e&&(r!=null&&r.transformResponse&&(e=await((y=r.transformResponse)==null?void 0:y.call(r,e,a().data))),r!=null&&r.onSuccess&&await((T=r.onSuccess)==null?void 0:T.call(r,e))),o&&(r!=null&&r.transformError&&(o=await((m=r.transformError)==null?void 0:m.call(r,o,a().error))),r!=null&&r.onError&&await((p=r.onError)==null?void 0:p.call(r,o))),e?(n({data:e,isSuccess:!0,isLoading:!1,isFetching:!1,cashExp:h?s:Date.now()+w,arg:t}),{data:e}):(n({isLoading:!1,isSuccess:!1,isFetching:!1,isError:!0,error:o,arg:t}),{error:o})}catch(e){return n({isLoading:!1,isSuccess:!1,isFetching:!1,isError:!0,error:e,arg:t}),{error:e}}};async function x(t,n,a,r,u,w,F,S,c){var p,e,o;let i={arg:t,def:r,get:a,set:n};for(let s of c)await((p=s.beforeQuery)==null?void 0:p.call(s,i));let y=-1,T=async s=>{if(s<=y)throw new Error("next() called multiple times");y=s;let b=S[s];return b?b(i,()=>T(s+1)):J(t,n,a,r,u,w,F)},m=await T(0);for(let s of c)await((e=s.afterQuery)==null?void 0:e.call(s,m,i));if(m!=null&&m.error)for(let s of c)await((o=s.onError)==null?void 0:o.call(s,m.error,i));return m}function N(t){let{baseQuery:n,endpoints:a,clashTimeout:r=30*1e3,middlewares:u=[],plugins:w=[]}=t,S=a({query:i=>({type:"query",queryFn:i.query,...i}),mutation:i=>({type:"mutation",queryFn:i.query,...i})}),c={};for(let i in S){let y=S[i],T=`use${v(i)}`+(y.type==="query"?"Query":"Mutation"),m=g((p,e)=>({data:null,isLoading:!1,isError:!1,isFetching:!1,isSuccess:!1,error:null,arg:null,cashExp:0,query:o=>x(o,p,e,y,n,r,!1,[...u,...y.middlewares||[]],[...w,...y.plugins||[]]),reFetch:()=>{var o;return x((o=e())==null?void 0:o.arg,p,e,y,n,r,!0,[...u,...y.middlewares||[]],[...w,...y.plugins||[]])}}));y.type==="query"&&(c[T]=(p,e)=>{let{skip:o}=e||{},{query:s,error:b,isError:h,isLoading:l,isSuccess:E,reFetch:q,data:Q}=m();return(0,A.useEffect)(()=>{o||s(p)},[JSON.stringify(p||{})]),{error:b,isError:h,isLoading:l,isSuccess:E,data:Q,reFetch:q}}),y.type==="mutation"&&(c[T]=()=>{let{query:p,...e}=m();return[p,e]})}return c}0&&(module.exports={createApi});
@@ -0,0 +1 @@
1
+ import{a as Q}from"../chunk-SISWF3T4.mjs";import{useEffect as k}from"react";function x(a){return a.charAt(0).toUpperCase()+a.slice(1)}var M=async(a,c,l,r,h,q,b)=>{var E,p,o,s,w,y,u;c({isLoading:!0});try{let n=null,t=null,i=l().cashExp,S=Date.now(),m=!1;if(b||JSON.stringify(l().arg||{})!==JSON.stringify(a||{})?m=!1:m=i>=S,m&&(n=l().data),!m&&(r!=null&&r.queryFnc)){c({isFetching:!0});let{data:e,error:F}=await((E=r==null?void 0:r.queryFnc)==null?void 0:E.call(r,a,h));e&&(n=e),F&&(t=F)}else{let e=r.queryFn(a);if(r!=null&&r.transformHeader&&(e.headers=await((p=r==null?void 0:r.transformHeader)==null?void 0:p.call(r,e==null?void 0:e.headers))),r!=null&&r.transformBody&&(e.body=await((o=r==null?void 0:r.transformBody)==null?void 0:o.call(r,e==null?void 0:e.body))),!m){c({isFetching:!0});let{data:F,error:A}=await h(e);F&&(n=F),A&&(t=A)}}return n&&(r!=null&&r.transformResponse&&(n=await((s=r.transformResponse)==null?void 0:s.call(r,n,l().data))),r!=null&&r.onSuccess&&await((w=r.onSuccess)==null?void 0:w.call(r,n))),t&&(r!=null&&r.transformError&&(t=await((y=r.transformError)==null?void 0:y.call(r,t,l().error))),r!=null&&r.onError&&await((u=r.onError)==null?void 0:u.call(r,t))),n?(c({data:n,isSuccess:!0,isLoading:!1,isFetching:!1,cashExp:m?i:Date.now()+q,arg:a}),{data:n}):(c({isLoading:!1,isSuccess:!1,isFetching:!1,isError:!0,error:t,arg:a}),{error:t})}catch(n){return c({isLoading:!1,isSuccess:!1,isFetching:!1,isError:!0,error:n,arg:a}),{error:n}}};async function T(a,c,l,r,h,q,b,E,p){var u,n,t;let o={arg:a,def:r,get:l,set:c};for(let i of p)await((u=i.beforeQuery)==null?void 0:u.call(i,o));let s=-1,w=async i=>{if(i<=s)throw new Error("next() called multiple times");s=i;let S=E[i];return S?S(o,()=>w(i+1)):M(a,c,l,r,h,q,b)},y=await w(0);for(let i of p)await((n=i.afterQuery)==null?void 0:n.call(i,y,o));if(y!=null&&y.error)for(let i of p)await((t=i.onError)==null?void 0:t.call(i,y.error,o));return y}function P(a){let{baseQuery:c,endpoints:l,clashTimeout:r=30*1e3,middlewares:h=[],plugins:q=[]}=a,E=l({query:o=>({type:"query",queryFn:o.query,...o}),mutation:o=>({type:"mutation",queryFn:o.query,...o})}),p={};for(let o in E){let s=E[o],w=`use${x(o)}`+(s.type==="query"?"Query":"Mutation"),y=Q((u,n)=>({data:null,isLoading:!1,isError:!1,isFetching:!1,isSuccess:!1,error:null,arg:null,cashExp:0,query:t=>T(t,u,n,s,c,r,!1,[...h,...s.middlewares||[]],[...q,...s.plugins||[]]),reFetch:()=>{var t;return T((t=n())==null?void 0:t.arg,u,n,s,c,r,!0,[...h,...s.middlewares||[]],[...q,...s.plugins||[]])}}));s.type==="query"&&(p[w]=(u,n)=>{let{skip:t}=n||{},{query:i,error:S,isError:m,isLoading:e,isSuccess:F,reFetch:A,data:g}=y();return k(()=>{t||i(u)},[JSON.stringify(u||{})]),{error:S,isError:m,isLoading:e,isSuccess:F,data:g,reFetch:A}}),s.type==="mutation"&&(p[w]=()=>{let{query:u,...n}=y();return[u,n]})}return p}export{P as createApi};
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "zustic",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A fast, minimal state management solution for React ecosystems. Works seamlessly with React, Next.js, and React Native, offering predictable state updates with a tiny footprint.",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
5
  "scripts": {
9
- "build": "tsup src/index.ts --format esm,cjs --dts --clean --external react",
10
- "start:cjs": "node dist/cjs/index.js",
11
- "start:esm": "node dist/esm/index.js",
12
- "start": "ts-node src/index.ts",
6
+ "build": "tsup",
13
7
  "test": "npm run build && npm link"
14
8
  },
15
9
  "exports": {
16
10
  ".": {
17
- "require": "./dist/index.js",
18
- "import": "./dist/index.mjs"
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js"
14
+ },
15
+ "./query": {
16
+ "types": "./dist/query/index.d.ts",
17
+ "import": "./dist/query/index.mjs",
18
+ "require": "./dist/query/index.js"
19
19
  }
20
20
  },
21
21
  "directories": {
@@ -38,7 +38,7 @@
38
38
  "nextjs",
39
39
  "state"
40
40
  ],
41
- "homepage": "https://github.com/DeveloperRejaul/zustic#readme",
41
+ "homepage": "https://zustic.github.io",
42
42
  "files": [
43
43
  "dist/**/*",
44
44
  "README.md"