@braine/quantum-query 1.2.6 → 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 +56 -297
- package/dist/index.cjs +866 -827
- package/dist/index.d.cts +138 -128
- package/dist/index.d.ts +138 -128
- package/dist/index.js +887 -839
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,332 +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.
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 📦 Installation
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npm install @braine/quantum-query
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 🚀 Quick Start (React Hooks)
|
|
29
|
-
|
|
30
|
-
If you just want to fetch data, it works exactly like you expect.
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
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
|
-
```
|
|
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)*
|
|
46
13
|
|
|
47
14
|
---
|
|
48
15
|
|
|
49
|
-
##
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* **Examples:** User Profile, List of Todos, Search Results.
|
|
56
|
-
* **Tool:** `useQuery`, `useMutation`.
|
|
57
|
-
|
|
58
|
-
### 2. App State (`createState`)
|
|
59
|
-
Data that belongs to the Interface. It is synchronous and temporary.
|
|
60
|
-
* **Examples:** Is Modal Open?, Current Filter, Form Inputs.
|
|
61
|
-
* **Tool:** `createState`, `useStore`.
|
|
62
|
-
|
|
63
|
-
### 🌉 The Bridge
|
|
64
|
-
Connect them seamlessly.
|
|
65
|
-
* **Store → Query**: Drive a query with a store signal.
|
|
66
|
-
```ts
|
|
67
|
-
const { filter } = useStore(uiStore);
|
|
68
|
-
const { data } = useQuery(['items', filter], fetchItems);
|
|
69
|
-
```
|
|
70
|
-
* **Query → Store**: Sync server data into a store for computed logic.
|
|
71
|
-
```ts
|
|
72
|
-
const bridge = fromSignal(query.signal);
|
|
73
|
-
// Now you can use 'bridge' inside your Proxy store logic!
|
|
74
|
-
```
|
|
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.
|
|
75
22
|
|
|
76
23
|
---
|
|
77
24
|
|
|
78
|
-
##
|
|
25
|
+
## Why Quantum?
|
|
79
26
|
|
|
80
|
-
|
|
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) |
|
|
81
34
|
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { defineModel } from '@braine/quantum-query';
|
|
35
|
+
## Quick Look
|
|
85
36
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
state: {
|
|
89
|
-
items: [] as string[],
|
|
90
|
-
filter: 'all',
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
// 2. Computed Properties (Auto-Memoized)
|
|
94
|
-
computed: {
|
|
95
|
-
activeCount() {
|
|
96
|
-
return this.items.length;
|
|
97
|
-
},
|
|
98
|
-
isEmpty() {
|
|
99
|
-
return this.items.length === 0;
|
|
100
|
-
}
|
|
101
|
-
},
|
|
37
|
+
```tsx
|
|
38
|
+
import { useQuery, useMutation } from '@braine/quantum-query';
|
|
102
39
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
},
|
|
108
|
-
async save() {
|
|
109
|
-
await api.post('/todos', { items: this.items });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
40
|
+
// 1. Standard Hooks (React Adapter)
|
|
41
|
+
const { data, isPending } = useQuery({
|
|
42
|
+
queryKey: ['user', 1],
|
|
43
|
+
queryFn: fetchUser
|
|
112
44
|
});
|
|
113
|
-
```
|
|
114
45
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
import { useStore } from '@braine/quantum-query';
|
|
118
|
-
import { TodoModel } from './models/TodoModel';
|
|
46
|
+
// 2. The Quantum Way (Zero-Render)
|
|
47
|
+
import { useQuery$, SignalValue } from '@braine/quantum-query';
|
|
119
48
|
|
|
120
|
-
function
|
|
121
|
-
//
|
|
122
|
-
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
|
+
});
|
|
123
56
|
|
|
124
57
|
return (
|
|
125
58
|
<div>
|
|
126
|
-
<
|
|
127
|
-
|
|
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>
|
|
128
64
|
</div>
|
|
129
65
|
);
|
|
130
66
|
}
|
|
131
67
|
```
|
|
132
68
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
## 🌐 Enterprise HTTP Client
|
|
136
|
-
|
|
137
|
-
We built a fetch wrapper that matches **RTK Query** in power but keeps **Axios** simplicity. It includes **Automatic Deduplication** and **Retries**.
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import { createHttpClient } from '@braine/quantum-query';
|
|
141
|
-
|
|
142
|
-
export const api = createHttpClient({
|
|
143
|
-
baseURL: 'https://api.myapp.com',
|
|
144
|
-
timeout: 5000,
|
|
145
|
-
retry: { retries: 3 }, // Exponential backoff for Network errors
|
|
146
|
-
|
|
147
|
-
// Auth Handling (Auto-Refresh)
|
|
148
|
-
auth: {
|
|
149
|
-
getToken: () => localStorage.getItem('token'),
|
|
150
|
-
onTokenExpired: async () => {
|
|
151
|
-
const newToken = await refreshToken();
|
|
152
|
-
localStorage.setItem('token', newToken);
|
|
153
|
-
return newToken; // Automatically retries original request
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
// data is strictly typed!
|
|
159
|
-
const user = await api.get<User>('/me');
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## 🔐 Authentication (Built-in)
|
|
165
|
-
|
|
166
|
-
No more interceptors. We handle token injection and **automatic refresh on 401** errors out of the box.
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
const client = createClient({
|
|
170
|
-
baseURL: 'https://api.myapp.com',
|
|
171
|
-
auth: {
|
|
172
|
-
// 1. Inject Token
|
|
173
|
-
getToken: () => localStorage.getItem('token'),
|
|
174
|
-
|
|
175
|
-
// 2. Refresh & Retry (Auto-called on 401)
|
|
176
|
-
onTokenExpired: async (client) => {
|
|
177
|
-
const newToken = await refreshToken();
|
|
178
|
-
localStorage.setItem('token', newToken);
|
|
179
|
-
return newToken; // Original request is automatically retried
|
|
180
|
-
},
|
|
181
|
-
|
|
182
|
-
// 3. Redirect on Fail
|
|
183
|
-
onAuthFailed: () => window.location.href = '/login'
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## 🛡️ Data Integrity (Runtime Safety)
|
|
191
|
-
|
|
192
|
-
Don't trust the backend. Validate it. We support **Zod**, **Valibot**, or **Yup** schemas directly in the hook.
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
import { z } from 'zod';
|
|
196
|
-
|
|
197
|
-
const UserSchema = z.object({
|
|
198
|
-
id: z.string(),
|
|
199
|
-
name: z.string(),
|
|
200
|
-
role: z.enum(['admin', 'user'])
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
const { data } = useQuery({
|
|
204
|
-
queryKey: ['user'],
|
|
205
|
-
queryFn: fetchUser,
|
|
206
|
-
schema: UserSchema // Throws descriptive error if API returns garbage
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
## 🔌 Plugin System (Middleware) 🆕
|
|
213
|
-
|
|
214
|
-
Inject logic into every request lifecycle (Logging, Analytics, Performance Monitoring).
|
|
215
|
-
|
|
216
|
-
```typescript
|
|
217
|
-
import { queryCache } from '@braine/quantum-query';
|
|
218
|
-
|
|
219
|
-
queryCache.use({
|
|
220
|
-
name: 'logger',
|
|
221
|
-
onFetchStart: (key) => console.log('Fetching', key),
|
|
222
|
-
onFetchError: (key, error) => console.error(`Fetch failed for ${key}:`, error)
|
|
223
|
-
});
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
---
|
|
227
|
-
|
|
228
|
-
## 💾 Persistence Adapter 🆕
|
|
229
|
-
|
|
230
|
-
Persist your cache to `localStorage` (or IndexedDB/AsyncStorage) automatically. Works offline.
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
import { persistQueryClient, createLocalStoragePersister } from '@braine/quantum-query/persist';
|
|
234
|
-
|
|
235
|
-
persistQueryClient({
|
|
236
|
-
queryClient: queryCache,
|
|
237
|
-
persister: createLocalStoragePersister(),
|
|
238
|
-
maxAge: 1000 * 60 * 60 * 24 // 24 hours
|
|
239
|
-
});
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## 🚀 Server-Side Rendering (SSR) 🆕
|
|
245
|
-
|
|
246
|
-
Full support for Next.js, Remix, and other SSR frameworks. We provide a simple hydration API to transfer state from server to client.
|
|
247
|
-
|
|
248
|
-
### Server (Next.js App Router)
|
|
249
|
-
```tsx
|
|
250
|
-
import { dehydrate, QueryCache, HydrationBoundary } from '@braine/quantum-query';
|
|
251
|
-
|
|
252
|
-
export default async function Page() {
|
|
253
|
-
const client = new QueryCache();
|
|
254
|
-
|
|
255
|
-
// Prefetch data on the server
|
|
256
|
-
await client.prefetch(['user', '1'], fetchUser);
|
|
257
|
-
|
|
258
|
-
// Serialize the cache
|
|
259
|
-
const dehydratedState = dehydrate(client);
|
|
260
|
-
|
|
261
|
-
return (
|
|
262
|
-
<HydrationBoundary state={dehydratedState}>
|
|
263
|
-
<ClientComponent />
|
|
264
|
-
</HydrationBoundary>
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
---
|
|
270
|
-
|
|
271
|
-
## ⚡️ Fine-Grained Selectors (Optimization) 🆕
|
|
69
|
+
## Unified Client State (Atoms)
|
|
272
70
|
|
|
273
|
-
|
|
71
|
+
Forget Redux/Zustand. Use the same primitive for client state.
|
|
274
72
|
|
|
275
73
|
```tsx
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
## 🛠️ DevTools (Debug Like a Pro)
|
|
291
|
-
|
|
292
|
-
Inspect your cache, force refetches, and view active listeners.
|
|
293
|
-
|
|
294
|
-
```tsx
|
|
295
|
-
import { QuantumDevTools } from '@braine/quantum-query/devtools';
|
|
296
|
-
|
|
297
|
-
function App() {
|
|
298
|
-
return (
|
|
299
|
-
<QueryClientProvider client={client}>
|
|
300
|
-
<YourApp />
|
|
301
|
-
<QuantumDevTools openByDefault={false} />
|
|
302
|
-
</QueryClientProvider>
|
|
303
|
-
);
|
|
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
|
+
);
|
|
304
87
|
}
|
|
305
88
|
```
|
|
306
89
|
|
|
307
|
-
---
|
|
308
|
-
|
|
309
|
-
## 📚 Documentation
|
|
310
|
-
|
|
311
|
-
* **[API Reference](docs/api.md)**: Full method signatures and options.
|
|
312
|
-
* **[Recipes](docs/recipes.md)**: Common patterns (Auth, Infinite Scroll, Optimistic UI).
|
|
313
|
-
* **[Migration Guide](docs/migration.md)**: Step-by-step guide from RTK Query / Redux.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## 🆚 Comparison
|
|
318
|
-
|
|
319
|
-
| Feature | RTK Query | TanStack Query | **Quantum-Query** |
|
|
320
|
-
| :--- | :--- | :--- | :--- |
|
|
321
|
-
| **Architecture** | Redux (Store + Slices) | Observers | **Atomic Signals** ✅ |
|
|
322
|
-
| **Boilerplate** | High (Provider + Store) | Medium | **Zero** ✅ |
|
|
323
|
-
| **Re-Renders** | Selector-based (O(n)) | Observer-based | **Signal-based (O(1))** ✅ |
|
|
324
|
-
| **Smart Models** | ❌ (Requires Redux) | ❌ | **Built-in** ✅ |
|
|
325
|
-
| **Bundle Size** | ~17kb | ~13kb | **~3kb** ✅ |
|
|
326
|
-
| **Deduplication** | Yes | Yes | **Yes** ✅ |
|
|
327
|
-
| **Persistence** | `redux-persist` | Experimental | **Built-in First Class** ✅ |
|
|
328
|
-
|
|
329
|
-
---
|
|
330
|
-
|
|
331
90
|
## License
|
|
332
91
|
MIT
|