react-smart-crud 0.1.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 +3 -0
- package/README.md +388 -0
- package/package.json +31 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
|
|
2
|
+
# react-smart-crud
|
|
3
|
+
Smart, minimal, and developer-controlled CRUD engine for React — with **Optimistic UI**, **zero prop-drilling**, and **no state management headache**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🔥 What is react-smart-crud?
|
|
8
|
+
|
|
9
|
+
`react-smart-crud` is a **lightweight state + CRUD utility** designed to remove the most painful parts of React CRUD development:
|
|
10
|
+
|
|
11
|
+
- ❌ No more endless `useState`
|
|
12
|
+
- ❌ No more `useEffect` refetch loops
|
|
13
|
+
- ❌ No prop drilling between components
|
|
14
|
+
- ❌ No forced toast / UI library
|
|
15
|
+
- ❌ No Redux / React Query overhead
|
|
16
|
+
|
|
17
|
+
👉 You write **business logic**, not plumbing.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🧠 Core Idea (Very Important)
|
|
22
|
+
|
|
23
|
+
> **One shared store per resource.
|
|
24
|
+
Optimistic first.
|
|
25
|
+
Server truth always wins.
|
|
26
|
+
Developer controls UI & UX.**
|
|
27
|
+
|
|
28
|
+
- Data lives in a **central in-memory store**
|
|
29
|
+
- Any component subscribed to that store updates automatically
|
|
30
|
+
- CRUD actions update UI instantly (optimistic)
|
|
31
|
+
- Server response finalizes or rolls back state
|
|
32
|
+
- Errors come directly from backend
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 😵 Problems This Library Solves
|
|
37
|
+
|
|
38
|
+
### Before (Typical React CRUD)
|
|
39
|
+
- `useState` in parent
|
|
40
|
+
- `useEffect` for fetch
|
|
41
|
+
- Props passed through 3–4 components
|
|
42
|
+
- Re-fetch list after every mutation
|
|
43
|
+
- Toast logic mixed with API logic
|
|
44
|
+
- Server error message lost
|
|
45
|
+
|
|
46
|
+
### After (react-smart-crud)
|
|
47
|
+
- ✅ No `useState` for list data
|
|
48
|
+
- ✅ No `useEffect` refetch
|
|
49
|
+
- ✅ No props drilling
|
|
50
|
+
- ✅ Instant UI update
|
|
51
|
+
- ✅ Manual toast control
|
|
52
|
+
- ✅ Real server error shown
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## ✨ Key Features
|
|
57
|
+
|
|
58
|
+
✅ Optimistic Create / Update / Delete
|
|
59
|
+
✅ No `useState` needed for CRUD data
|
|
60
|
+
✅ No `useEffect` dependency hell
|
|
61
|
+
✅ No props drilling between components
|
|
62
|
+
✅ Works across **multiple components automatically**
|
|
63
|
+
✅ Manual toast / notification control
|
|
64
|
+
✅ Backend error message preserved
|
|
65
|
+
✅ Automatic rollback on failure
|
|
66
|
+
✅ REST API friendly
|
|
67
|
+
✅ Extremely small & fast
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 👥 Who Is This For?
|
|
72
|
+
|
|
73
|
+
### Perfect for:
|
|
74
|
+
- React dashboard projects
|
|
75
|
+
- Admin panels
|
|
76
|
+
- School / ERP / CRM systems
|
|
77
|
+
- MERN stack apps
|
|
78
|
+
- Freelancers & agencies
|
|
79
|
+
- Developers tired of over-engineering
|
|
80
|
+
|
|
81
|
+
### Not meant for:
|
|
82
|
+
- Offline-first apps
|
|
83
|
+
- GraphQL heavy caching
|
|
84
|
+
- Real-time sync systems
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 🆚 Comparison With Existing Solutions
|
|
89
|
+
|
|
90
|
+
| Feature | react-smart-crud | React Query | Redux |
|
|
91
|
+
|------|------------------|-------------|-------|
|
|
92
|
+
| useState needed | ❌ No | ❌ No | ❌ No |
|
|
93
|
+
| useEffect needed | ❌ No | ❌ No | ❌ No |
|
|
94
|
+
| Prop drilling | ❌ No | ❌ No | ❌ No |
|
|
95
|
+
| Optimistic UI | ✅ Simple | ⚠️ Complex | ⚠️ Manual |
|
|
96
|
+
| Toast control | ✅ Full | ❌ Indirect | ❌ Indirect |
|
|
97
|
+
| Boilerplate | 🔥 Very Low | Medium | High |
|
|
98
|
+
| Learning curve | ⭐ Easy | ⭐⭐ Medium | ⭐⭐⭐ Hard |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📦 Installation
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
npm install react-smart-crud
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
Optional (for UI notifications)
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
npm install react-hot-toast
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
⚠️ **Toast library is NOT required**
|
|
117
|
+
|
|
118
|
+
You can use:
|
|
119
|
+
|
|
120
|
+
* Modal
|
|
121
|
+
* Alert
|
|
122
|
+
* Snackbar
|
|
123
|
+
* Custom UI
|
|
124
|
+
* Or nothing at all
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 🗂️ Recommended Folder Structure
|
|
129
|
+
|
|
130
|
+
```txt
|
|
131
|
+
src/
|
|
132
|
+
├─ smart-crud/
|
|
133
|
+
│ ├─ config.js # baseUrl & token config
|
|
134
|
+
│ ├─ http.js # fetch wrapper
|
|
135
|
+
│ ├─ store.js # central data store
|
|
136
|
+
│ ├─ crud.js # create / update / delete
|
|
137
|
+
│ └─ index.js # exports
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## ⚙️ Configuration
|
|
143
|
+
|
|
144
|
+
### `config.js`
|
|
145
|
+
|
|
146
|
+
```js
|
|
147
|
+
export const config = {
|
|
148
|
+
baseUrl: "",
|
|
149
|
+
getToken: null,
|
|
150
|
+
notify: null // ✅ toast handler
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function setupCrud(options = {}) {
|
|
154
|
+
config.baseUrl = options.baseUrl || ""
|
|
155
|
+
config.getToken = options.getToken || null
|
|
156
|
+
config.notify = options.notify || null
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Why this design?
|
|
162
|
+
|
|
163
|
+
* `baseUrl` → auto applied everywhere
|
|
164
|
+
* `getToken` → optional, dynamic
|
|
165
|
+
* Works with:
|
|
166
|
+
|
|
167
|
+
* JWT
|
|
168
|
+
* Cookie-based auth
|
|
169
|
+
* Public APIs
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## 🌐 HTTP Layer (Server Error Safe)
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
import { config } from "./config";
|
|
177
|
+
|
|
178
|
+
export async function request(url, options = {}) {
|
|
179
|
+
const headers = {
|
|
180
|
+
"Content-Type": "application/json",
|
|
181
|
+
...(options.headers || {}),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// 🔐 token optional
|
|
185
|
+
if (config.getToken) {
|
|
186
|
+
const token = config.getToken();
|
|
187
|
+
if (token) {
|
|
188
|
+
headers.Authorization = `Bearer ${token}`;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const res = await fetch(config.baseUrl + url, {
|
|
193
|
+
...options,
|
|
194
|
+
headers,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// 🟢 body safe parse
|
|
198
|
+
const data = await res.json().catch(() => ({}));
|
|
199
|
+
|
|
200
|
+
// 🔴 IMPORTANT FIX
|
|
201
|
+
if (!res.ok) {
|
|
202
|
+
throw {
|
|
203
|
+
status: res.status,
|
|
204
|
+
message: data.message || "Something went wrong",
|
|
205
|
+
data,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return data;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Benefits
|
|
215
|
+
|
|
216
|
+
✔ Backend error message preserved
|
|
217
|
+
✔ UI controls error display
|
|
218
|
+
✔ No generic error forcing
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 🧠 Store Concept (No useState, No Props)
|
|
223
|
+
|
|
224
|
+
* One store per resource
|
|
225
|
+
* Shared across all components
|
|
226
|
+
* Subscribers auto re-render
|
|
227
|
+
|
|
228
|
+
### What you DON’T do anymore
|
|
229
|
+
|
|
230
|
+
* ❌ No `useState` for lists
|
|
231
|
+
* ❌ No `useEffect` for fetching
|
|
232
|
+
* ❌ No prop drilling
|
|
233
|
+
* ❌ No manual syncing
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## ✍️ Usage Examples
|
|
238
|
+
|
|
239
|
+
### CREATE (Optimistic + Toast)
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
createItem(
|
|
243
|
+
"users",
|
|
244
|
+
{
|
|
245
|
+
email: form.email,
|
|
246
|
+
password: form.password,
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
optimistic: (data) => ({
|
|
250
|
+
email: data.email,
|
|
251
|
+
role: "user",
|
|
252
|
+
}),
|
|
253
|
+
|
|
254
|
+
onSuccess: () => toast.success("User created"),
|
|
255
|
+
onError: () => toast.error("Failed to create"),
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
### UPDATE (Optimistic Patch)
|
|
263
|
+
|
|
264
|
+
```js
|
|
265
|
+
updateItem(
|
|
266
|
+
"users",
|
|
267
|
+
editingUser.id,
|
|
268
|
+
{
|
|
269
|
+
email: form.email,
|
|
270
|
+
role: form.role,
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
optimistic: (old, patch) => ({
|
|
274
|
+
...old,
|
|
275
|
+
email: patch.email,
|
|
276
|
+
role: patch.role,
|
|
277
|
+
}),
|
|
278
|
+
onSuccess: () => {
|
|
279
|
+
toast.success("Profile updated");
|
|
280
|
+
clearEdit(); // ✅ Clear
|
|
281
|
+
},
|
|
282
|
+
onError: (err) => toast.error(err.message),
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### DELETE
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
deleteItem("users", id, {
|
|
293
|
+
onError: (err) => toast.error(err.message),
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## ⚡ Optimistic UI Flow
|
|
300
|
+
|
|
301
|
+
1. UI updates instantly
|
|
302
|
+
2. API request is sent
|
|
303
|
+
3. Server success → finalize data
|
|
304
|
+
4. Server error → rollback
|
|
305
|
+
5. Subscribers re-render automatically
|
|
306
|
+
|
|
307
|
+
No refetch
|
|
308
|
+
No flicker
|
|
309
|
+
No confusion
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## ❗ Error Handling (Real Server Message)
|
|
314
|
+
|
|
315
|
+
### Backend
|
|
316
|
+
|
|
317
|
+
```js
|
|
318
|
+
res.status(400).json({ message: "Invalid role" });
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Frontend
|
|
322
|
+
|
|
323
|
+
```js
|
|
324
|
+
onError: (err) => toast.error(err.message);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
✔ User sees exact server message
|
|
328
|
+
✔ You control UX
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
## 🧩 Why No useEffect?
|
|
333
|
+
|
|
334
|
+
* Data already exists in store
|
|
335
|
+
* Subscribers handle re-render
|
|
336
|
+
* No dependency array bugs
|
|
337
|
+
* No infinite loops
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## 🧩 Why No useState?
|
|
342
|
+
|
|
343
|
+
* CRUD data is shared
|
|
344
|
+
* Multiple components use same data
|
|
345
|
+
* Manual syncing is fragile
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## 🧩 Why No Prop Drilling?
|
|
350
|
+
|
|
351
|
+
* Store is global per resource
|
|
352
|
+
* Components subscribe directly
|
|
353
|
+
* Clean and scalable
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## 🚀 Best Use Cases
|
|
358
|
+
|
|
359
|
+
* Admin dashboards
|
|
360
|
+
* Management systems
|
|
361
|
+
* Internal tools
|
|
362
|
+
* CRUD-heavy applications
|
|
363
|
+
* Rapid MVPs
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## ❤️ Philosophy
|
|
368
|
+
|
|
369
|
+
> Simple tools scale better than complex abstractions.
|
|
370
|
+
|
|
371
|
+
No magic
|
|
372
|
+
No hidden behavior
|
|
373
|
+
Just predictable CRUD
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 📄 License
|
|
378
|
+
|
|
379
|
+
MIT — free to use, modify, and ship.
|
|
380
|
+
|
|
381
|
+
---
|
|
382
|
+
|
|
383
|
+
## 🙌 Final Note
|
|
384
|
+
|
|
385
|
+
If you understand basic React,
|
|
386
|
+
you already understand **react-smart-crud**.
|
|
387
|
+
|
|
388
|
+
Happy coding 🚀
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-smart-crud",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Minimal optimistic CRUD helper for React without useState, useEffect, or prop drilling",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"react",
|
|
13
|
+
"crud",
|
|
14
|
+
"optimistic-ui",
|
|
15
|
+
"state-management",
|
|
16
|
+
"react-hooks",
|
|
17
|
+
"admin-dashboard"
|
|
18
|
+
],
|
|
19
|
+
"author": "Tarequl Islam",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/tareq-dev/react-smart-crud"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": ">=16.8"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"vite": "^7.3.0"
|
|
30
|
+
}
|
|
31
|
+
}
|