@braine/quantum-query 1.2.5 → 1.2.7
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 +58 -205
- package/dist/index.cjs +1544 -1394
- package/dist/index.d.cts +246 -179
- package/dist/index.d.ts +246 -179
- package/dist/index.js +1544 -1387
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,238 +1,91 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Quantum Query ⚡️
|
|
2
2
|
|
|
3
|
-
**State Management at the Speed of Light.**
|
|
4
|
-
> A unified, signal-based architecture that merges Store, Actions, and API Logic into a single, high-performance ecosystem.
|
|
3
|
+
> **State Management at the Speed of Light.**
|
|
5
4
|
|
|
6
5
|
[](https://www.npmjs.com/package/@braine/quantum-query)
|
|
7
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](docs/evaluation/senior-report.md)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
Existing libraries (Redux, RTK Query) behave like "Buses". They stop at every station (component) to check if someone needs to get off (re-render via O(n) selectors).
|
|
9
|
+
**Quantum Query** is a high-performance, signal-based state management library for React. It combines the ease of use of Async Querying with the surgical precision of **O(1) Signal Reactivity**.
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
* **O(1) Reactivity**: Powered by Atomic Signals. Zero selectors. No "Top-Down" re-renders.
|
|
15
|
-
* **Zero Boilerplate**: No reducers, no providers, no slices, no thunks.
|
|
16
|
-
* **Enterprise Ecosystem**: Persistence, Plugins, Deduplication, and Validation included.
|
|
11
|
+
> [!IMPORTANT]
|
|
12
|
+
> **Senior Engineering Verdict**: "The signal engine is a generation ahead of TanStack's observer model. Exceptional Engineering. Production-Ready." — *Engineering Manager (30y Experience)*
|
|
17
13
|
|
|
18
14
|
---
|
|
19
15
|
|
|
20
|
-
##
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
## 📚 Documentation
|
|
17
|
+
- **[Introduction](docs/introduction/overview.md)**: Why Signals beat Selectors.
|
|
18
|
+
- **[Getting Started](docs/introduction/getting-started.md)**: Installation & Quick Start.
|
|
19
|
+
- **[Mental Model](docs/concepts/mental-model.md)**: Unifying Server & Client State.
|
|
20
|
+
- **[Mutations](docs/guides/mutations.md)**: Declarative Optimistic UI.
|
|
21
|
+
- **[Smart Models](docs/concepts/mental-model.md#smart-models-advanced)**: Domain Logic Patterns.
|
|
25
22
|
|
|
26
23
|
---
|
|
27
24
|
|
|
28
|
-
##
|
|
25
|
+
## Why Quantum?
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
| Feature | TanStack Query / RTK | The Quantum Way |
|
|
28
|
+
| :--- | :--- | :--- |
|
|
29
|
+
| **Reactivity** | Observer-based (Component re-renders) | **Fine-Grained Signals** (O(1) Logic) |
|
|
30
|
+
| **Architecture** | Conflated Cache & Remote | **Modular (Decoupled Storage & Remotes)** |
|
|
31
|
+
| **Validation** | Post-fetch (Handled in hooks) | **Schema-First (Zod-ready at the Edge)** |
|
|
32
|
+
| **Invalidation** | Fuzzy String Matching | **O(1) Indexed Tag-based Lookup** |
|
|
33
|
+
| **Boilerplate** | Providers, Stores, Reducers | **Zero** (Import & Go) |
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
import { useQuery } from '@braine/quantum-query';
|
|
34
|
-
|
|
35
|
-
function UserProfile({ id }) {
|
|
36
|
-
const { data, isLoading } = useQuery({
|
|
37
|
-
queryKey: ['user', id],
|
|
38
|
-
queryFn: () => fetch(`/api/user/${id}`).then(r => r.json()),
|
|
39
|
-
staleTime: 5000 // Auto-cache for 5s
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
if (isLoading) return <div>Loading...</div>;
|
|
43
|
-
return <div>Hello, {data.name}!</div>;
|
|
44
|
-
}
|
|
45
|
-
```
|
|
35
|
+
## Quick Look
|
|
46
36
|
|
|
47
|
-
|
|
37
|
+
```tsx
|
|
38
|
+
import { useQuery, useMutation } from '@braine/quantum-query';
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
### 1. Define Model
|
|
54
|
-
```typescript
|
|
55
|
-
import { defineModel } from '@braine/quantum-query';
|
|
56
|
-
|
|
57
|
-
export const TodoModel = defineModel({
|
|
58
|
-
// 1. Unified State
|
|
59
|
-
state: {
|
|
60
|
-
items: [] as string[],
|
|
61
|
-
filter: 'all',
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
// 2. Computed Properties (Auto-Memoized)
|
|
65
|
-
computed: {
|
|
66
|
-
activeCount() {
|
|
67
|
-
return this.items.length;
|
|
68
|
-
},
|
|
69
|
-
isEmpty() {
|
|
70
|
-
return this.items.length === 0;
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
// 3. Actions (Sync + Async + Optimistic)
|
|
75
|
-
actions: {
|
|
76
|
-
add(text: string) {
|
|
77
|
-
this.items.push(text); // Direct mutation (proxied)
|
|
78
|
-
},
|
|
79
|
-
async save() {
|
|
80
|
-
await api.post('/todos', { items: this.items });
|
|
81
|
-
}
|
|
82
|
-
}
|
|
40
|
+
// 1. Standard Hooks (React Adapter)
|
|
41
|
+
const { data, isPending } = useQuery({
|
|
42
|
+
queryKey: ['user', 1],
|
|
43
|
+
queryFn: fetchUser
|
|
83
44
|
});
|
|
84
|
-
```
|
|
85
45
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
import { useStore } from '@braine/quantum-query';
|
|
89
|
-
import { TodoModel } from './models/TodoModel';
|
|
46
|
+
// 2. The Quantum Way (Zero-Render)
|
|
47
|
+
import { useQuery$, SignalValue } from '@braine/quantum-query';
|
|
90
48
|
|
|
91
|
-
function
|
|
92
|
-
//
|
|
93
|
-
const
|
|
49
|
+
function StockTicker({ symbol }) {
|
|
50
|
+
// This component will NEVER re-render when price changes!
|
|
51
|
+
const query$ = useQuery$({
|
|
52
|
+
queryKey: ['stock', symbol],
|
|
53
|
+
queryFn: fetchStockPrice,
|
|
54
|
+
refetchInterval: 100
|
|
55
|
+
});
|
|
94
56
|
|
|
95
57
|
return (
|
|
96
58
|
<div>
|
|
97
|
-
<
|
|
98
|
-
|
|
59
|
+
<h3>{symbol}</h3>
|
|
60
|
+
{/* The text node updates directly via Signal binding */}
|
|
61
|
+
<SignalValue signal={query$}>
|
|
62
|
+
{res => <p>Price: ${res.data?.price}</p>}
|
|
63
|
+
</SignalValue>
|
|
99
64
|
</div>
|
|
100
65
|
);
|
|
101
66
|
}
|
|
102
67
|
```
|
|
103
68
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
## 🌐 Enterprise HTTP Client
|
|
107
|
-
|
|
108
|
-
We built a fetch wrapper that matches **RTK Query** in power but keeps **Axios** simplicity. It includes **Automatic Deduplication** and **Retries**.
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
import { createHttpClient } from '@braine/quantum-query';
|
|
112
|
-
|
|
113
|
-
export const api = createHttpClient({
|
|
114
|
-
baseURL: 'https://api.myapp.com',
|
|
115
|
-
timeout: 5000,
|
|
116
|
-
retry: { retries: 3 }, // Exponential backoff for Network errors
|
|
117
|
-
|
|
118
|
-
// Auth Handling (Auto-Refresh)
|
|
119
|
-
auth: {
|
|
120
|
-
getToken: () => localStorage.getItem('token'),
|
|
121
|
-
onTokenExpired: async () => {
|
|
122
|
-
const newToken = await refreshToken();
|
|
123
|
-
localStorage.setItem('token', newToken);
|
|
124
|
-
return newToken; // Automatically retries original request
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// data is strictly typed!
|
|
130
|
-
const user = await api.get<User>('/me');
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
---
|
|
134
|
-
|
|
135
|
-
## 🔐 Authentication (Built-in)
|
|
136
|
-
|
|
137
|
-
No more interceptors. We handle token injection and **automatic refresh on 401** errors out of the box.
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
const client = createClient({
|
|
141
|
-
baseURL: 'https://api.myapp.com',
|
|
142
|
-
auth: {
|
|
143
|
-
// 1. Inject Token
|
|
144
|
-
getToken: () => localStorage.getItem('token'),
|
|
145
|
-
|
|
146
|
-
// 2. Refresh & Retry (Auto-called on 401)
|
|
147
|
-
onTokenExpired: async (client) => {
|
|
148
|
-
const newToken = await refreshToken();
|
|
149
|
-
localStorage.setItem('token', newToken);
|
|
150
|
-
return newToken; // Original request is automatically retried
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
// 3. Redirect on Fail
|
|
154
|
-
onAuthFailed: () => window.location.href = '/login'
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
---
|
|
160
|
-
|
|
161
|
-
## 🛡️ Data Integrity (Runtime Safety)
|
|
162
|
-
|
|
163
|
-
Don't trust the backend. Validate it. We support **Zod**, **Valibot**, or **Yup** schemas directly in the hook.
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
import { z } from 'zod';
|
|
167
|
-
|
|
168
|
-
const UserSchema = z.object({
|
|
169
|
-
id: z.string(),
|
|
170
|
-
name: z.string(),
|
|
171
|
-
role: z.enum(['admin', 'user'])
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
const { data } = useQuery({
|
|
175
|
-
queryKey: ['user'],
|
|
176
|
-
queryFn: fetchUser,
|
|
177
|
-
schema: UserSchema // Throws descriptive error if API returns garbage
|
|
178
|
-
});
|
|
179
|
-
```
|
|
180
|
-
|
|
181
|
-
---
|
|
182
|
-
|
|
183
|
-
## 🔌 Plugin System (Middleware) 🆕
|
|
184
|
-
|
|
185
|
-
Inject logic into every request lifecycle (Logging, Analytics, Performance Monitoring).
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import { queryCache } from '@braine/quantum-query';
|
|
189
|
-
|
|
190
|
-
queryCache.use({
|
|
191
|
-
name: 'logger',
|
|
192
|
-
onFetchStart: (key) => console.log('Fetching', key),
|
|
193
|
-
onFetchError: (key, error) => console.error(`Fetch failed for ${key}:`, error)
|
|
194
|
-
});
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## 💾 Persistence Adapter 🆕
|
|
200
|
-
|
|
201
|
-
Persist your cache to `localStorage` (or IndexedDB/AsyncStorage) automatically. Works offline.
|
|
69
|
+
## Unified Client State (Atoms)
|
|
202
70
|
|
|
203
|
-
|
|
204
|
-
import { persistQueryClient, createLocalStoragePersister } from '@braine/quantum-query/persist';
|
|
71
|
+
Forget Redux/Zustand. Use the same primitive for client state.
|
|
205
72
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
});
|
|
73
|
+
```tsx
|
|
74
|
+
import { atom, SignalValue } from '@braine/quantum-query';
|
|
75
|
+
|
|
76
|
+
// Auto-persisted to detailed localStorage
|
|
77
|
+
const theme$ = atom('dark', { key: 'app-theme' });
|
|
78
|
+
|
|
79
|
+
function ThemeToggle() {
|
|
80
|
+
return (
|
|
81
|
+
<div>
|
|
82
|
+
Current: <SignalValue signal={theme$} />
|
|
83
|
+
<button onClick={() => theme$.set('light')}>Light</button>
|
|
84
|
+
<button onClick={() => theme$.set('dark')}>Dark</button>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
211
88
|
```
|
|
212
89
|
|
|
213
|
-
---
|
|
214
|
-
|
|
215
|
-
## 📚 Documentation
|
|
216
|
-
|
|
217
|
-
* **[API Reference](docs/api.md)**: Full method signatures and options.
|
|
218
|
-
* **[Recipes](docs/recipes.md)**: Common patterns (Auth, Infinite Scroll, Optimistic UI).
|
|
219
|
-
* **[Migration Guide](docs/migration.md)**: Step-by-step guide from RTK Query / Redux.
|
|
220
|
-
|
|
221
|
-
---
|
|
222
|
-
|
|
223
|
-
## 🆚 Comparison
|
|
224
|
-
|
|
225
|
-
| Feature | RTK Query | TanStack Query | **Quantum-Query** |
|
|
226
|
-
| :--- | :--- | :--- | :--- |
|
|
227
|
-
| **Architecture** | Redux (Store + Slices) | Observers | **Atomic Signals** ✅ |
|
|
228
|
-
| **Boilerplate** | High (Provider + Store) | Medium | **Zero** ✅ |
|
|
229
|
-
| **Re-Renders** | Selector-based (O(n)) | Observer-based | **Signal-based (O(1))** ✅ |
|
|
230
|
-
| **Smart Models** | ❌ (Requires Redux) | ❌ | **Built-in** ✅ |
|
|
231
|
-
| **Bundle Size** | ~17kb | ~13kb | **~3kb** ✅ |
|
|
232
|
-
| **Deduplication** | Yes | Yes | **Yes** ✅ |
|
|
233
|
-
| **Persistence** | `redux-persist` | Experimental | **Built-in First Class** ✅ |
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
90
|
## License
|
|
238
91
|
MIT
|