react-smart-query 1.0.0 β†’ 1.0.1

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.
Files changed (2) hide show
  1. package/README.md +169 -73
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,130 +1,226 @@
1
- # 🧠 React Smart Query
1
+ # 🧠 react-smart-query
2
2
 
3
- **Production-grade, offline-first, normalized data orchestration for React Native and Web.**
4
-
5
- React Smart Query is more than just a cache; it's a high-performance normalization engine designed to handle complex, paginated lists with predictable, O(log n) mutations β€” even when offline.
3
+ **Offline-first normalized data layer for React Native & Web**
6
4
 
7
5
  [![npm version](https://img.shields.io/npm/v/react-smart-query.svg)](https://www.npmjs.com/package/react-smart-query)
8
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
7
 
10
8
  ---
11
9
 
12
- ## πŸš€ Why React Smart Query?
10
+ ## ⚑ Quick Example
11
+
12
+ Get started in seconds. It looks just like the tools you already know, but with superpowers.
13
+
14
+ ```tsx
15
+ import { useSmartQuery } from 'react-smart-query';
16
+
17
+ const { data, isLoading } = useSmartQuery({
18
+ queryKey: ["expenses"],
19
+ queryFn: fetchExpenses
20
+ });
21
+ ```
22
+
23
+ ---
24
+
25
+ ## 🚨 The Problem
26
+
27
+ TanStack Query (React Query) handles data fetching brilliantly. But as your app grows, real-world constraints start to show. Complex apps often struggle with:
28
+
29
+ - **Pagination + Mutation Bugs**: Updating a single item buried inside page 3 of an infinite list requires complex, error-prone manual cache traversals.
30
+ - **Offline Sync**: Surviving patchy networks and syncing user actions when they come back online.
31
+ - **Unnecessary Re-renders**: UI components rendering more often than they need to.
32
+ - **Large List Updates**: Finding and updating items in massive arrays without freezing the UI.
33
+
34
+ ---
35
+
36
+ ## πŸ’‘ The Solution
13
37
 
14
- Handling mutations in paginated lists (Infinite Scroll) is notoriously difficult in modern UI frameworks. Standard tooling often results in:
15
- 1. **Data Duplication:** The same resource existing in multiple pages of a query response cache, leading to out-of-sync UI components.
16
- 2. **Inconsistent Ordering:** Newly added optimistic items appearing at the top/bottom rather than their correct sorted semantic position, causing visual "jumps" on next load.
17
- 3. **Complex Manual Cache Logic:** Forcing developers to write intricate, error-prone traversal logic just to update a single nested item deep inside a page array.
38
+ `react-smart-query` intercepts your API responses and stores them intelligently.
18
39
 
19
- **React Smart Query solves this by adopting a Unified Normalized Storage model.**
40
+ - **Adds offline-first support** right out of the box.
41
+ - **Uses normalized storage** (a flat dictionary) behind the scenes for lighting-fast updates.
42
+ - **Fixes pagination + mutation issues** automatically. No more manual cache traversal!
43
+ - **Works on top of React Query**. It enhances your existing setup without replacing it.
20
44
 
21
- Instead of storing data exactly as the API returns it (as a paginated chunk of arrays), React Smart Query intercepts the data, extracts individual entities (using your provided `getItemId`), and stores them in a single, perfectly sorted, globally accessible dictionary (`byId`) and array (`allIds`).
45
+ ---
22
46
 
23
- - **O(log n) Sorted Mutations**: Items are inserted into the single, global sorted list using binary search. Adding a new item guarantees it instantly lands in the mathematically correct position according to your `sortComparator`.
24
- - **Automatic Deduplication**: Because items are normalized by ID, an item fetched in Page 1 and (erroneously) returned again in Page 3 only ever exists once in the engine.
25
- - **Offline-First & Auto-Sync**: A built-in mutation queue automatically captures changes made while offline, persists them to local storage (MMKV/IndexedDB), and plays them back to your server seamlessly when the connection returns.
26
- - **Derived Pagination**: Pagination is treated strictly as a "slice" view over your normalized data, not how the data is stored. Your UI always receives perfectly contiguous, sorted data.
27
- - **Memory Protected**: Automatic "soft trimming" algorithm monitors list sizes and safely drops least-recently-seen items to prevent infinite scroll memory bloat on low-end devices.
47
+ ## ✨ Key Features
48
+
49
+ - πŸ“Ά **Offline-first caching** (MMKV for mobile, IndexedDB for web)
50
+ - πŸš€ **Normalized data structure** (`{ byId, allIds }` map) for `O(1)` updates
51
+ - 🧠 **Smart diff updates** (minimal, surgically precise re-renders)
52
+ - πŸ“œ **Infinite query with normalized pagination** (no more page-splicing bugs)
53
+ - 🌍 **Global mutation system** (add/update/remove from anywhere, without hooks)
54
+ - πŸ“± **Cross-platform support**
55
+ - πŸ›‘οΈ **Memory protection** (maxItems to elegantly trim huge lists)
56
+
57
+ ---
28
58
 
29
- ### How it compares to TanStack Query
59
+ ## βš–οΈ Why Not Just TanStack Query?
30
60
 
31
- React Smart Query is **built on top of** TanStack Query. It uses TanStack Query for the networking, background refetching, and general request lifecycle, but completely replaces how the returned data is cached and mutated.
61
+ React Smart Query takes the heavy lifting out of state mutability. It delegates the networking to TanStack Query and completely upgrades the storage.
32
62
 
33
- | Feature | TanStack Query | React Smart Query |
34
- | :--- | :--- | :--- |
35
- | **Primary Focus** | Server State Synchronization | Normalized Data Orchestration & Mutability |
36
- | **Data Storage** | Raw API Responses (Arrays/Objects) | Unified Normalized Dictionary (`byId` & `allIds`) |
37
- | **Infinite List Mutations** | Manual Cache Traversal (`setQueryData`) | `O(log n)` Binary Search Auto-Insertions |
38
- | **Deduplication** | Across identical URL endpoints | Across entire application by Item ID |
39
- | **Offline Mutations** | Difficult (Requires manual hydration/plugins) | Built-in Persistent Queue & Auto-Sync |
40
- | **Memory Management** | Time-based garbage collection | Time-based + Soft trimming of large lists |
63
+ | Feature | TanStack Query | react-smart-query |
64
+ | :--- | :---: | :---: |
65
+ | **Offline queue** | ❌ | βœ… |
66
+ | **Normalized cache** | ❌ | βœ… |
67
+ | **Pagination + mutation fix** | ❌ | βœ… |
68
+ | **Global mutations** | ❌ | βœ… |
41
69
 
42
70
  ---
43
71
 
44
72
  ## πŸ“¦ Installation
45
73
 
74
+ Install the library alongside its peer dependencies:
75
+
46
76
  ```bash
47
77
  npm install react-smart-query @tanstack/react-query react-native-mmkv
48
78
  ```
49
79
 
50
80
  ---
51
81
 
52
- ## πŸ› οΈ Quick Start
82
+ ## 🚦 Quick Start
83
+
84
+ ### 1. Setup
53
85
 
54
- ### 1. Basic Query
86
+ Just wrap your app like you normally would. Your data layer is instantly primed.
55
87
 
56
88
  ```tsx
57
- import { useSmartQuery } from 'react-smart-query';
89
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
58
90
 
59
- const { data, isLoading } = useSmartQuery({
60
- queryKey: ['profile'],
61
- queryFn: () => api.get('/me'),
62
- select: (res) => res.user,
63
- });
91
+ const queryClient = new QueryClient();
92
+
93
+ export default function App() {
94
+ return (
95
+ <QueryClientProvider client={queryClient}>
96
+ <YourApp />
97
+ </QueryClientProvider>
98
+ );
99
+ }
64
100
  ```
65
101
 
66
- ### 2. Infinite Scroll (The Real Magic)
102
+ ### 2. Standard Query
67
103
 
68
104
  ```tsx
69
- const { data, addItem, fetchNextPage } = useInfiniteSmartQuery({
70
- queryKey: ['expenses'],
71
- queryFn: ({ pageParam }) => api.get('/expenses', { cursor: pageParam }),
72
- getNextCursor: (res) => res.nextCursor,
73
- select: (res) => res.items,
74
- getItemId: (item) => item.id,
75
- sortComparator: (a, b) => b.createdAt - a.createdAt, // Perfect sort across all pages
76
- });
105
+ import { useSmartQuery } from 'react-smart-query';
106
+
107
+ function UserProfile({ userId }) {
108
+ const { data } = useSmartQuery({
109
+ queryKey: ['users', userId],
110
+ queryFn: () => api.getUser(userId),
111
+ select: (res) => res.user,
112
+ });
113
+
114
+ return <Text>{data?.name}</Text>;
115
+ }
116
+ ```
77
117
 
78
- // Adding an item "just works" and inserts into the correct sorted position
79
- const onAdd = () => addItem({ id: '123', description: 'Coffee', createdAt: Date.now() });
118
+ ### 3. Infinite Query
119
+
120
+ This is where the magic happens. Mutating paged data is now effortless.
121
+
122
+ ```tsx
123
+ import { useInfiniteSmartQuery } from 'react-smart-query';
124
+
125
+ function Feed() {
126
+ const { data, addItem } = useInfiniteSmartQuery({
127
+ queryKey: ['feed'],
128
+ queryFn: ({ pageParam }) => api.getFeed({ cursor: pageParam }),
129
+ getNextCursor: (res) => res.nextCursor,
130
+ select: (res) => res.items,
131
+ getItemId: (item) => item.id,
132
+ sortComparator: (a, b) => b.createdAt - a.createdAt,
133
+ });
134
+
135
+ // Adding an item automatically sorts it into the exact right place!
136
+ const onNewPost = (post) => addItem(post);
137
+
138
+ return <FlatList data={data} renderItem={...} />;
139
+ }
80
140
  ```
81
141
 
82
142
  ---
83
143
 
144
+ ## πŸ’Ό Example Use Case
145
+
146
+ **Scenario: An Expense Tracking App**
147
+
148
+ Imagine a user is traveling through the subway and logs an expense.
149
+ 1. `react-smart-query` immediately intercepts this.
150
+ 2. It pushes the action to an **Offline Queue**.
151
+ 3. It performs a **Global Mutation**, inserting the new expense into the normalized store.
152
+ 4. Your Infinite List jumps to lifeβ€”it finds the expense, uses your `sortComparator` via binary search to place it at exactly the top of the list, and triggers a surgically precise re-render.
153
+ 5. When the user exits the subway, the queue detects the network and syncs the expense to your server.
154
+
155
+ **Perfect for:** Expense Apps, Chat Apps, Social Feeds, and Dashboards.
156
+
157
+ ---
158
+
159
+ ## πŸ› οΈ API Overview
160
+
161
+ - **`useSmartQuery`**: Drop-in enhancement for viewing and caching standard API calls.
162
+ - **`useInfiniteSmartQuery`**: The flagship hook. Takes paginated API chunks, flattens them, sorts them globally, and gives you `addItem`, `updateItem`, and `removeItem` helpers.
163
+ - **`getSmartQueryActions`**: A global API to mutate data from outside of React components (e.g., from a push notification background handler).
164
+
165
+ ---
166
+
84
167
  ## πŸ—οΈ Architecture
85
168
 
86
- ```mermaid
87
- graph TD
88
- A[Component] -->|useInfiniteSmartQuery| B(Normalization Engine)
89
- B -->|Sorted Binary Insert| C[Unified Normalized List]
90
- C -->|O1 Lookup| D[(byId Map)]
91
- C -->|Sorted Order| E[(allIds Array)]
92
- B -->|Persist| F[Storage Adapter]
93
- F -->|Mobile| G[(MMKV)]
94
- F -->|Web| H[(IndexedDB)]
95
- I[Global Registry] -->|Mutate from Background| B
169
+ ```text
170
+ UI (React Components)
171
+ ↓
172
+ Smart Query Hooks
173
+ ↓
174
+ TanStack Query (Networking)
175
+ ↓
176
+ Normalized Cache + Offline Queue
177
+ ↓
178
+ Storage (MMKV / IndexedDB)
179
+ ```
180
+
181
+ ---
182
+
183
+ ## πŸ•΅οΈ Debug Tools
184
+
185
+ For power users, `react-smart-query` comes with built-in development inspection tools to see exactly how your data is normalizing.
186
+
187
+ ```tsx
188
+ import "react-smart-query/debug";
189
+ import { smartQueryDebug } from "react-smart-query";
190
+
191
+ // Prints the exact current state of the global { byId, allIds } maps to your console!
192
+ await smartQueryDebug.snapshot();
96
193
  ```
97
194
 
98
195
  ---
99
196
 
100
- ## πŸ”₯ Professional Features
197
+ ## πŸ€” When to Use / Not Use
101
198
 
102
- - **Mutation Conflict Guards**: Prevents stale background updates from overwriting fresher local data.
103
- - **Batch Updates**: Group multiple mutations into a single storage write and render.
104
- - **Smart Diffing**: 5-tier hybrid comparison ensures components only re-render when data actually changes.
105
- - **DevTools**: Inspect internal normalized state, cache hits/misses, and in-flight requests in development.
199
+ βœ… **Use if:**
200
+ - You are building offline-first apps.
201
+ - You have large, paginated lists.
202
+ - You have high-frequency data updates (websocket chats, real-time feeds).
203
+
204
+ ❌ **Avoid if:**
205
+ - You are building a very small app without offline needs.
206
+ - Your data is purely static and never mutates locally.
106
207
 
107
208
  ---
108
209
 
109
- ## πŸ’‘ When to use?
210
+ ## πŸ—ΊοΈ Roadmap
110
211
 
111
- βœ… **Use if**:
112
- - You have high-frequency updates in paginated lists (e.g., Chat, Feeds, Transactions).
113
- - You need robust offline support with optimistic UI.
114
- - You want to eliminate "flicker" when items change positions.
212
+ - [ ] DevTools UI (Visual Inspector)
213
+ - [ ] Built-in WebSocket sync adapter
214
+ - [ ] Lightweight Plugin System
115
215
 
116
- ❌ **Avoid if**:
117
- - Your data is small and non-relational.
118
- - You don't need offline persistence or sorted lists.
216
+ ---
119
217
 
120
- ## πŸ“š Full Documentation
218
+ ## 🀝 Contributing
121
219
 
122
- For advanced usages, hooks APIs, and architectural guidelines, please see the full documentation:
123
- - [API Reference](./docs/API_REFERENCE.md)
124
- - [Guidelines & Best Practices](./docs/GUIDELINES.md)
125
- - [Testing & Debugging](./docs/TESTING.md)
220
+ We welcome contributions! Whether you're fixing a bug, adding a feature, or improving documentation, check out our repository and open a Pull Request.
126
221
 
127
222
  ---
128
223
 
129
224
  ## πŸ“„ License
225
+
130
226
  MIT Β© 2024 React Smart Query Team
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-smart-query",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Offline-first, normalized, cache-versioned data layer for React Native and Expo. Built on TanStack Query with MMKV (native) and IndexedDB (web).",
5
5
  "author": "Subham Ghosh <subham49ghosh@gmail.com>",
6
6
  "license": "MIT",