vasuzex 2.3.12 → 2.3.14

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/CHANGELOG.md CHANGED
@@ -2,6 +2,123 @@
2
2
 
3
3
  All notable changes to Vasuzex will be documented in this file.
4
4
 
5
+ ## [2.3.14] - 2026-04-08
6
+
7
+ ### 🐛 Fixed
8
+
9
+ #### DataTable — Content Loader (Skeleton) on Sort/Search/Filter (`vasuzex/react`)
10
+
11
+ **Root Causes & Fixes:**
12
+
13
+ 1. **Browser Paint Timing Issue** — Skeleton loader not visible on sort/search (only on explicit refresh click)
14
+ - **Root cause**: React 18 `createRoot` + fast localhost API responses (2-10ms) meant the skeleton commit and data response both arrived within the same vsync frame (~16ms), so the browser only painted the final data state
15
+ - **Fix**: `useLayoutEffect` commits skeleton synchronously + `rAF → setTimeout(0)` defers XHR until AFTER browser paint
16
+ - **Technical flow**:
17
+ 1. `useLayoutEffect` → skeleton committed to DOM (synchronously, before paint)
18
+ 2. Passive effect queues `rAF` → scheduled pre-paint
19
+ 3. `rAF` queues `setTimeout(0)` → scheduled as macro-task (after paint)
20
+ 4. Browser **paints skeleton** ← now visible to user
21
+ 5. `setTimeout(0)` fires → `fetchData()` → XHR opens → response arrives after skeleton is on screen
22
+
23
+ 2. **API Client Error Interceptor Stripping Cancel Errors** — "No data found" briefly appeared on every sort/search
24
+ - **Root cause**: axios cancel errors have `err.code === 'ERR_CANCELED'` which DataTable checks — but error interceptor transformed ALL errors to plain `{ message, errors }` objects, stripping the code/name properties
25
+ - **Impact**: Cancelled requests hit the error path → `setData([])` + `setLoading(false)` → "No data found" flash, then data arrived
26
+ - **Fix**: Both api clients (`admin/web` and `business/web`) now check `if (axios.isCancel(error))` early and pass through untransformed
27
+
28
+ 3. **Double-Fetch on Every Interaction** — Multiple concurrent requests on sort/search
29
+ - **Root cause**: `refreshSignal` and `refreshKey` effects had `fetchData` in deps. `fetchData` recreates on every sort/search (because its own deps change). Since every admin page passes `refreshSignal={refreshKey}`, BOTH the main fetch effect AND the refreshSignal effect fired on every interaction → 2+ concurrent requests
30
+ - **Fix**: Introduced `fetchDataRef` — holds always-current `fetchData` without needing it in secondary effect deps. Secondary effects now only fire when their actual trigger (`refreshSignal` value or `refreshKey` value) changes
31
+
32
+ 4. **Tailwind CSS Classes Not Generated** — animate-pulse skeleton class missing from bundle
33
+ - **Root cause**: Admin web's `tailwind.config.js` only scanned `./src/**/*`, not the symlinked `vasuzex-v2` directory
34
+ - **Impact**: `animate-pulse` utility class not in admin web's CSS bundle (business web already had correct path)
35
+ - **Fix**: Added `../../../vasuzex-v2/frontend/react-ui/**/*.{js,jsx}` to Tailwind content array (matching business web pattern)
36
+
37
+ **Files Modified:**
38
+ - [`DataTable.jsx`](frontend/react-ui/components/DataTable/DataTable.jsx) — useLayoutEffect + rAF+setTimeout pattern + fetchDataRef
39
+ - `apps/admin/web/src/lib/api-client.js` — axios.isCancel check before error transformation
40
+ - `apps/business/web/src/lib/apiClient.js` — axios.isCancel check before error transformation
41
+ - `apps/admin/web/tailwind.config.js` — added vasuzex-v2 path to content array
42
+
43
+ **Result:** Skeleton loader now reliably shows on sort, search, filter, and every other data trigger, then data smoothly renders when ready. No "no data found" flash.
44
+
45
+ #### Model — Soft-Delete Restore Fix (`vasuzex/eloquent`)
46
+
47
+ - **Issue**: `restore()` method used `save()` which triggered model observers and allowed normal query scopes, causing inconsistent state
48
+ - **Fix**: Direct database update via `withTrashed()` query builder to bypass soft-delete scope
49
+ - **Changes**:
50
+ - Use `withTrashed().where(pk, id).update()` instead of `save()`
51
+ - Auto-update `updated_at` timestamp when timestamps enabled
52
+ - Calls `syncOriginal()` to update model cache state
53
+ - Fires `restored` model event after DB update completes
54
+ - **Impact**: Soft-deleted records now restore cleanly without triggering update observers
55
+
56
+ #### MediaManager — WebP/AVIF Format Negotiation (`vasuzex/services`)
57
+
58
+ - **Issue**: Media serving didn't support modern image formats (WebP, AVIF) or client content-type negotiation
59
+ - **Enhancements**:
60
+ 1. **Format negotiation** — Query param `?format=webp|avif|jpeg|png` overrides client Accept header
61
+ 2. **LRU in-memory cache** — Hot thumbnails cached in memory (200 entry limit) to avoid repeated filesystem hits
62
+ 3. **Format-aware disk cache keys** — WebP and JPEG of same image cached separately
63
+ 4. **ETag support** — Content MD5 hash for conditional requests (304 Not Modified)
64
+ 5. **Immutable cache headers** — 1-year max-age via dedicated controller
65
+ 6. **Direct format lookup** — Cache lookup by format (no extension loop)
66
+ - **Performance**: 5-50x faster for repeated hot thumbnail requests
67
+ - **Files Modified**: [`framework/Services/Media/MediaManager.js`](framework/Services/Media/MediaManager.js)
68
+
69
+ ### ✨ Added
70
+
71
+ #### ActionDefaults — Hard Delete & Restore Actions (`vasuzex/react`)
72
+
73
+ - **Hard Delete Action** — Permanent delete with severe confirmation (Flame icon 🔥)
74
+ - Shows in trash-only mode for trashed records
75
+ - `DELETE ?hardDelete=true` query parameter
76
+ - `createHardDeleteClickHandler()` helper
77
+ - "Cannot be undone" warning in confirmation dialog
78
+
79
+ - **Restore Action** — Restore soft-deleted records (RotateCcw icon)
80
+ - Shows for trashed rows
81
+ - `PATCH {restoreUrl}` request
82
+ - `createRestoreClickHandler()` helper
83
+ - Smooth restore with toast notification
84
+
85
+ - **Custom Action Tooltip** — Auto-generate tooltip from label when title not provided
86
+ - Improves UX for custom actions without explicit title
87
+
88
+ **Files Modified:** [`frontend/react-ui/components/DataTable/ActionDefaults.jsx`](frontend/react-ui/components/DataTable/ActionDefaults.jsx)
89
+
90
+ **Impact:** Complete soft-delete/trash workflow now supported in DataTable — view, restore, or permanently delete with proper confirmations.
91
+
92
+
93
+ ## [2.3.13] - 2026-04-05
94
+
95
+ ### 🐛 Fixed
96
+
97
+ #### DataTable — Debounce + In-Flight Request Cancellation (`vasuzex/react`)
98
+
99
+ - **Debounced column search** — Column search input now waits 400 ms after the user stops typing before sending a request to the server. Previously, a request was fired on every keypress, causing API flooding for fast typists. ([`DataTable.jsx`](frontend/react-ui/components/DataTable/DataTable.jsx))
100
+
101
+ - **AbortController on in-flight requests** — If the user starts typing again while a previous search request is still in flight, that request is now automatically aborted before the new debounce window starts. This prevents stale responses from arriving out-of-order and updating the table with old data.
102
+
103
+ - **Unmount cleanup** — Any pending request is aborted when the DataTable component unmounts, preventing setState calls on unmounted components.
104
+
105
+ **Technical details:**
106
+ - Added `debouncedColumnSearch` state (derived from `columnSearch` with 400 ms debounce)
107
+ - Added `columnSearchDebounceRef` (`useRef`) — timer handle for the debounce
108
+ - Added `abortControllerRef` (`useRef`) — holds the `AbortController` for the current fetch
109
+ - `fetchData` useCallback now: aborts previous controller → creates new `AbortController` → passes `signal` to `api.get()` → catches `AbortError`/`ERR_CANCELED` silently
110
+ - Reset-page effect (`useEffect`) updated to depend on `debouncedColumnSearch` instead of `columnSearch`
111
+
112
+ ### 📝 Changed
113
+
114
+ #### README — Complete Rewrite
115
+ - Removed outdated alpha/V2 migration content
116
+ - Rebuilt from the live documentation at **https://vasuzex.xdeve.com/guide/**
117
+ - Covers: requirements, quick start, project structure, architecture, HTTP layer, Eloquent models, React UI, CLI reference, environment config, and full documentation index
118
+ - Proper badges (npm version, downloads, license, Node.js, pnpm)
119
+
120
+ ---
121
+
5
122
  ## [2.3.0] - 2026-02-18
6
123
 
7
124
  ### 🚀 Standalone Script Support