vasuzex 2.1.17 → 2.1.19
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/frontend/react-ui/components/DataTable/ActionDefaults.jsx +8 -7
- package/frontend/react-ui/components/DataTable/CellComponents/ApprovalStatusCell.jsx +60 -0
- package/frontend/react-ui/components/DataTable/CellComponents/RowActionsCell.jsx +212 -0
- package/frontend/react-ui/components/DataTable/CellComponents/index.js +9 -0
- package/frontend/react-ui/components/DataTable/TableBody.jsx +2 -2
- package/frontend/react-ui/components/DataTable/index.js +3 -0
- package/package.json +39 -30
- package/.ai-memory/LOGGER_STRICT_POLICY.md +0 -201
- package/.ai-memory/neastore-feature-mapping.md +0 -1114
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Eye, Edit2, Trash2 } from "lucide-react";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ActionDefaults - Production Ready
|
|
5
5
|
*
|
|
6
6
|
* Default configurations for common DataTable actions
|
|
7
7
|
* Provides sensible defaults for edit, view, delete, and switch actions
|
|
8
|
+
* Uses lucide-react icons matching RowActionsCell design
|
|
8
9
|
*
|
|
9
10
|
* @module components/DataTable/ActionDefaults
|
|
10
11
|
*/
|
|
@@ -13,26 +14,26 @@ export const ACTION_DEFAULTS = {
|
|
|
13
14
|
edit: {
|
|
14
15
|
type: "link",
|
|
15
16
|
label: "Edit",
|
|
16
|
-
icon:
|
|
17
|
+
icon: Edit2,
|
|
17
18
|
title: "Edit",
|
|
18
19
|
extraClass:
|
|
19
|
-
"
|
|
20
|
+
"p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30",
|
|
20
21
|
},
|
|
21
22
|
view: {
|
|
22
23
|
type: "button",
|
|
23
24
|
label: "View Details",
|
|
24
|
-
icon:
|
|
25
|
+
icon: Eye,
|
|
25
26
|
title: "View Details",
|
|
26
27
|
extraClass:
|
|
27
|
-
"
|
|
28
|
+
"p-1.5 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-blue-400 dark:hover:bg-blue-950/30",
|
|
28
29
|
},
|
|
29
30
|
delete: {
|
|
30
31
|
type: "button",
|
|
31
32
|
label: "Delete",
|
|
32
|
-
icon:
|
|
33
|
+
icon: Trash2,
|
|
33
34
|
title: "Delete",
|
|
34
35
|
extraClass:
|
|
35
|
-
"
|
|
36
|
+
"p-1.5 text-gray-600 hover:text-rose-600 hover:bg-rose-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-rose-400 dark:hover:bg-rose-950/30",
|
|
36
37
|
},
|
|
37
38
|
switch: {
|
|
38
39
|
type: "button",
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApprovalStatusCell Component
|
|
3
|
+
*
|
|
4
|
+
* Reusable read-only status pill for approval workflows
|
|
5
|
+
* Displays status with icon and soft background colors
|
|
6
|
+
*
|
|
7
|
+
* @module components/DataTable/CellComponents
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import PropTypes from 'prop-types';
|
|
12
|
+
import { CheckCircle, XCircle, Clock } from 'lucide-react';
|
|
13
|
+
|
|
14
|
+
const STATUS_CONFIG = {
|
|
15
|
+
pending: {
|
|
16
|
+
icon: Clock,
|
|
17
|
+
label: 'Pending',
|
|
18
|
+
bgClass: 'bg-amber-50 dark:bg-amber-950/30',
|
|
19
|
+
textClass: 'text-amber-700 dark:text-amber-400',
|
|
20
|
+
},
|
|
21
|
+
approved: {
|
|
22
|
+
icon: CheckCircle,
|
|
23
|
+
label: 'Approved',
|
|
24
|
+
bgClass: 'bg-emerald-50 dark:bg-emerald-950/30',
|
|
25
|
+
textClass: 'text-emerald-700 dark:text-emerald-400',
|
|
26
|
+
},
|
|
27
|
+
rejected: {
|
|
28
|
+
icon: XCircle,
|
|
29
|
+
label: 'Rejected',
|
|
30
|
+
bgClass: 'bg-rose-50 dark:bg-rose-950/30',
|
|
31
|
+
textClass: 'text-rose-700 dark:text-rose-400',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* ApprovalStatusCell - Professional status indicator
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} props
|
|
39
|
+
* @param {string} props.status - Approval status: 'pending'|'approved'|'rejected'
|
|
40
|
+
* @returns {JSX.Element}
|
|
41
|
+
*/
|
|
42
|
+
export function ApprovalStatusCell({ status }) {
|
|
43
|
+
const config = STATUS_CONFIG[status] || STATUS_CONFIG.pending;
|
|
44
|
+
const Icon = config.icon;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<span
|
|
48
|
+
className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md text-xs font-medium ${config.bgClass} ${config.textClass}`}
|
|
49
|
+
>
|
|
50
|
+
<Icon className="h-3.5 w-3.5" />
|
|
51
|
+
{config.label}
|
|
52
|
+
</span>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ApprovalStatusCell.propTypes = {
|
|
57
|
+
status: PropTypes.oneOf(['pending', 'approved', 'rejected']).isRequired,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default ApprovalStatusCell;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RowActionsCell Component
|
|
3
|
+
*
|
|
4
|
+
* Reusable actions cell with primary icons + overflow menu pattern
|
|
5
|
+
* Follows modern admin dashboard design (Amazon Seller/Stripe/Blinkit)
|
|
6
|
+
*
|
|
7
|
+
* @module components/DataTable/CellComponents
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { useState, useRef, useEffect } from 'react';
|
|
11
|
+
import PropTypes from 'prop-types';
|
|
12
|
+
import { Eye, Edit2, MoreVertical, CheckCircle, XCircle, History, Power, Trash2 } from 'lucide-react';
|
|
13
|
+
import { Link } from 'react-router-dom';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* RowActionsCell - Professional actions menu for data tables
|
|
17
|
+
*
|
|
18
|
+
* @param {Object} props
|
|
19
|
+
* @param {Object} props.row - Row data object
|
|
20
|
+
* @param {Function} props.onView - View action handler
|
|
21
|
+
* @param {Function} props.onEdit - Edit action handler (optional if editPath provided)
|
|
22
|
+
* @param {string} props.editPath - Edit page path (will be passed to Link)
|
|
23
|
+
* @param {Function} props.onToggle - Toggle status handler
|
|
24
|
+
* @param {Function} props.onDelete - Delete action handler
|
|
25
|
+
* @param {Function} props.onApprove - Approve action handler (approval workflows)
|
|
26
|
+
* @param {Function} props.onReject - Reject action handler (approval workflows)
|
|
27
|
+
* @param {Function} props.onViewHistory - View approval history handler
|
|
28
|
+
* @param {boolean} props.hasApproval - Whether to show approval actions (default: false)
|
|
29
|
+
* @returns {JSX.Element}
|
|
30
|
+
*/
|
|
31
|
+
export function RowActionsCell({
|
|
32
|
+
row,
|
|
33
|
+
onView,
|
|
34
|
+
onEdit,
|
|
35
|
+
editPath,
|
|
36
|
+
onToggle,
|
|
37
|
+
onDelete,
|
|
38
|
+
onApprove,
|
|
39
|
+
onReject,
|
|
40
|
+
onViewHistory,
|
|
41
|
+
hasApproval = false,
|
|
42
|
+
}) {
|
|
43
|
+
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
44
|
+
const menuRef = useRef(null);
|
|
45
|
+
const isPending = hasApproval && row.approval_status === 'pending';
|
|
46
|
+
|
|
47
|
+
// Close menu when clicking outside
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
const handleClickOutside = (event) => {
|
|
50
|
+
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
51
|
+
setIsMenuOpen(false);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
if (isMenuOpen) {
|
|
56
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
57
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
58
|
+
}
|
|
59
|
+
}, [isMenuOpen]);
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="flex items-center gap-2">
|
|
63
|
+
{/* Primary Actions - Always Visible */}
|
|
64
|
+
<button
|
|
65
|
+
onClick={() => onView(row)}
|
|
66
|
+
className="p-1.5 text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-blue-400 dark:hover:bg-blue-950/30"
|
|
67
|
+
title="View Details"
|
|
68
|
+
aria-label="View Details"
|
|
69
|
+
>
|
|
70
|
+
<Eye className="h-4 w-4" />
|
|
71
|
+
</button>
|
|
72
|
+
|
|
73
|
+
{editPath ? (
|
|
74
|
+
<Link
|
|
75
|
+
to={editPath}
|
|
76
|
+
className="p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30"
|
|
77
|
+
title="Edit"
|
|
78
|
+
aria-label="Edit"
|
|
79
|
+
>
|
|
80
|
+
<Edit2 className="h-4 w-4" />
|
|
81
|
+
</Link>
|
|
82
|
+
) : (
|
|
83
|
+
onEdit && (
|
|
84
|
+
<button
|
|
85
|
+
onClick={() => onEdit(row)}
|
|
86
|
+
className="p-1.5 text-gray-600 hover:text-emerald-600 hover:bg-emerald-50 rounded-md transition-colors dark:text-gray-400 dark:hover:text-emerald-400 dark:hover:bg-emerald-950/30"
|
|
87
|
+
title="Edit"
|
|
88
|
+
aria-label="Edit"
|
|
89
|
+
>
|
|
90
|
+
<Edit2 className="h-4 w-4" />
|
|
91
|
+
</button>
|
|
92
|
+
)
|
|
93
|
+
)}
|
|
94
|
+
|
|
95
|
+
{/* Overflow Menu - Secondary & Destructive Actions */}
|
|
96
|
+
<div className="relative" ref={menuRef}>
|
|
97
|
+
<button
|
|
98
|
+
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
|
99
|
+
className="p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-md transition-colors dark:text-gray-400 dark:hover:text-gray-100 dark:hover:bg-gray-700"
|
|
100
|
+
title="More Actions"
|
|
101
|
+
aria-label="More Actions"
|
|
102
|
+
aria-expanded={isMenuOpen}
|
|
103
|
+
>
|
|
104
|
+
<MoreVertical className="h-4 w-4" />
|
|
105
|
+
</button>
|
|
106
|
+
|
|
107
|
+
{isMenuOpen && (
|
|
108
|
+
<div className="absolute right-0 mt-1 w-48 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 z-50 py-1">
|
|
109
|
+
{/* Approval Actions - Only show when pending */}
|
|
110
|
+
{hasApproval && isPending && (
|
|
111
|
+
<>
|
|
112
|
+
{onApprove && (
|
|
113
|
+
<button
|
|
114
|
+
onClick={() => {
|
|
115
|
+
onApprove(row);
|
|
116
|
+
setIsMenuOpen(false);
|
|
117
|
+
}}
|
|
118
|
+
className="w-full flex items-center gap-3 px-4 py-2 text-sm text-emerald-700 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/30"
|
|
119
|
+
>
|
|
120
|
+
<CheckCircle className="h-4 w-4" />
|
|
121
|
+
<span>Approve</span>
|
|
122
|
+
</button>
|
|
123
|
+
)}
|
|
124
|
+
{onReject && (
|
|
125
|
+
<button
|
|
126
|
+
onClick={() => {
|
|
127
|
+
onReject(row);
|
|
128
|
+
setIsMenuOpen(false);
|
|
129
|
+
}}
|
|
130
|
+
className="w-full flex items-center gap-3 px-4 py-2 text-sm text-rose-700 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950/30"
|
|
131
|
+
>
|
|
132
|
+
<XCircle className="h-4 w-4" />
|
|
133
|
+
<span>Reject</span>
|
|
134
|
+
</button>
|
|
135
|
+
)}
|
|
136
|
+
<div className="border-t border-gray-200 dark:border-gray-700 my-1" />
|
|
137
|
+
</>
|
|
138
|
+
)}
|
|
139
|
+
|
|
140
|
+
{/* View History */}
|
|
141
|
+
{hasApproval && onViewHistory && (
|
|
142
|
+
<>
|
|
143
|
+
<button
|
|
144
|
+
onClick={() => {
|
|
145
|
+
onViewHistory(row);
|
|
146
|
+
setIsMenuOpen(false);
|
|
147
|
+
}}
|
|
148
|
+
className="w-full flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-700"
|
|
149
|
+
>
|
|
150
|
+
<History className="h-4 w-4" />
|
|
151
|
+
<span>View History</span>
|
|
152
|
+
</button>
|
|
153
|
+
<div className="border-t border-gray-200 dark:border-gray-700 my-1" />
|
|
154
|
+
</>
|
|
155
|
+
)}
|
|
156
|
+
|
|
157
|
+
{/* Toggle Status */}
|
|
158
|
+
{onToggle && (
|
|
159
|
+
<button
|
|
160
|
+
onClick={() => {
|
|
161
|
+
onToggle(row);
|
|
162
|
+
setIsMenuOpen(false);
|
|
163
|
+
}}
|
|
164
|
+
className="w-full flex items-center gap-3 px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-gray-700"
|
|
165
|
+
>
|
|
166
|
+
<Power className="h-4 w-4" />
|
|
167
|
+
<div className="flex flex-col items-start">
|
|
168
|
+
<span>Toggle Status</span>
|
|
169
|
+
<span className="text-xs text-gray-500 dark:text-gray-400">
|
|
170
|
+
{row.is_active ? 'Deactivate' : 'Activate'}
|
|
171
|
+
</span>
|
|
172
|
+
</div>
|
|
173
|
+
</button>
|
|
174
|
+
)}
|
|
175
|
+
|
|
176
|
+
{/* Delete - Always last, always red */}
|
|
177
|
+
{onDelete && (
|
|
178
|
+
<>
|
|
179
|
+
<div className="border-t border-gray-200 dark:border-gray-700 my-1" />
|
|
180
|
+
<button
|
|
181
|
+
onClick={() => {
|
|
182
|
+
onDelete(row);
|
|
183
|
+
setIsMenuOpen(false);
|
|
184
|
+
}}
|
|
185
|
+
className="w-full flex items-center gap-3 px-4 py-2 text-sm text-rose-700 hover:bg-rose-50 dark:text-rose-400 dark:hover:bg-rose-950/30"
|
|
186
|
+
>
|
|
187
|
+
<Trash2 className="h-4 w-4" />
|
|
188
|
+
<span>Delete</span>
|
|
189
|
+
</button>
|
|
190
|
+
</>
|
|
191
|
+
)}
|
|
192
|
+
</div>
|
|
193
|
+
)}
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
RowActionsCell.propTypes = {
|
|
200
|
+
row: PropTypes.object.isRequired,
|
|
201
|
+
onView: PropTypes.func,
|
|
202
|
+
onEdit: PropTypes.func,
|
|
203
|
+
editPath: PropTypes.string,
|
|
204
|
+
onToggle: PropTypes.func,
|
|
205
|
+
onDelete: PropTypes.func,
|
|
206
|
+
onApprove: PropTypes.func,
|
|
207
|
+
onReject: PropTypes.func,
|
|
208
|
+
onViewHistory: PropTypes.func,
|
|
209
|
+
hasApproval: PropTypes.bool,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export default RowActionsCell;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vasuzex/react - DataTable Cell Components
|
|
3
|
+
* Reusable cell renderers for common patterns
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { ApprovalStatusCell } from './ApprovalStatusCell.jsx';
|
|
7
|
+
export { RowActionsCell } from './RowActionsCell.jsx';
|
|
8
|
+
export { default as ApprovalStatusCellDefault } from './ApprovalStatusCell.jsx';
|
|
9
|
+
export { default as RowActionsCellDefault } from './RowActionsCell.jsx';
|
|
@@ -75,7 +75,7 @@ export function TableBody({
|
|
|
75
75
|
|
|
76
76
|
{/* Render Actions */}
|
|
77
77
|
{actions && (
|
|
78
|
-
<td className="px-
|
|
78
|
+
<td className="px-2 py-2 text-right">
|
|
79
79
|
<div className="flex items-center justify-end gap-2">
|
|
80
80
|
{actions.map((userAction, actionIdx) => {
|
|
81
81
|
// Check visibility first
|
|
@@ -146,7 +146,7 @@ export function TableBody({
|
|
|
146
146
|
const content = action.renderContent ? (
|
|
147
147
|
action.renderContent(row)
|
|
148
148
|
) : Icon ? (
|
|
149
|
-
<Icon className="h-
|
|
149
|
+
<Icon className="h-4 w-4" />
|
|
150
150
|
) : (
|
|
151
151
|
action.label
|
|
152
152
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vasuzex",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.19",
|
|
4
4
|
"description": "Laravel-inspired framework for Node.js monorepos - V2 with optimized dependencies",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./framework/index.js",
|
|
@@ -48,6 +48,34 @@
|
|
|
48
48
|
"#config": "./config/index.cjs",
|
|
49
49
|
"#config/*": "./config/*"
|
|
50
50
|
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"dev": "turbo run dev",
|
|
53
|
+
"build": "turbo run build",
|
|
54
|
+
"start": "turbo run start",
|
|
55
|
+
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
56
|
+
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
|
|
57
|
+
"test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
58
|
+
"db:migrate": "npx vasuzex migrate",
|
|
59
|
+
"test:all": "NODE_OPTIONS=--experimental-vm-modules npx jest",
|
|
60
|
+
"test:unit": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/unit",
|
|
61
|
+
"test:integration": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/integration",
|
|
62
|
+
"test:e2e": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/e2e",
|
|
63
|
+
"scan:issues": "node deep-scan-issues.cjs",
|
|
64
|
+
"dev:pilot-test-api": "turbo run dev --filter=pilot-test-api",
|
|
65
|
+
"start:pilot-test-api": "turbo run start --filter=pilot-test-api",
|
|
66
|
+
"dev:pilot-test-web": "turbo run dev --filter=pilot-test-web",
|
|
67
|
+
"start:pilot-test-web": "turbo run start --filter=pilot-test-web",
|
|
68
|
+
"dev:integration-test-api": "turbo run dev --filter=integration-test-api",
|
|
69
|
+
"start:integration-test-api": "turbo run start --filter=integration-test-api",
|
|
70
|
+
"dev:test-gen-api-api": "turbo run dev --filter=test-gen-api-api",
|
|
71
|
+
"start:test-gen-api-api": "turbo run start --filter=test-gen-api-api",
|
|
72
|
+
"dev:cleanup-test-api": "turbo run dev --filter=cleanup-test-api",
|
|
73
|
+
"start:cleanup-test-api": "turbo run start --filter=cleanup-test-api",
|
|
74
|
+
"dev:auth-integration-test-api": "turbo run dev --filter=auth-integration-test-api",
|
|
75
|
+
"start:auth-integration-test-api": "turbo run start --filter=auth-integration-test-api",
|
|
76
|
+
"dev:e2e-test-api": "turbo run dev --filter=e2e-test-api",
|
|
77
|
+
"start:e2e-test-api": "turbo run start --filter=e2e-test-api"
|
|
78
|
+
},
|
|
51
79
|
"keywords": [
|
|
52
80
|
"framework",
|
|
53
81
|
"laravel",
|
|
@@ -87,6 +115,7 @@
|
|
|
87
115
|
"joi": "^17.13.3",
|
|
88
116
|
"jose": "^6.1.3",
|
|
89
117
|
"jsonwebtoken": "^9.0.3",
|
|
118
|
+
"lucide-react": "^0.553.0",
|
|
90
119
|
"maxmind": "^5.0.1",
|
|
91
120
|
"multer": "^2.0.2",
|
|
92
121
|
"node-plop": "^0.32.3",
|
|
@@ -124,6 +153,13 @@
|
|
|
124
153
|
"turbo": "^2.6.1",
|
|
125
154
|
"vite": "^5.0.0"
|
|
126
155
|
},
|
|
156
|
+
"pnpm": {
|
|
157
|
+
"overrides": {
|
|
158
|
+
"express": "^5.2.1",
|
|
159
|
+
"react": "^18.2.0",
|
|
160
|
+
"vue": "^3.4.0"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
127
163
|
"repository": {
|
|
128
164
|
"type": "git",
|
|
129
165
|
"url": "git+https://github.com/rishicool/vasuzex.git"
|
|
@@ -132,32 +168,5 @@
|
|
|
132
168
|
"url": "https://github.com/rishicool/vasuzex/issues"
|
|
133
169
|
},
|
|
134
170
|
"homepage": "https://github.com/rishicool/vasuzex#readme",
|
|
135
|
-
"
|
|
136
|
-
|
|
137
|
-
"build": "turbo run build",
|
|
138
|
-
"start": "turbo run start",
|
|
139
|
-
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
140
|
-
"test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch",
|
|
141
|
-
"test:coverage": "NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
142
|
-
"db:migrate": "npx vasuzex migrate",
|
|
143
|
-
"test:all": "NODE_OPTIONS=--experimental-vm-modules npx jest",
|
|
144
|
-
"test:unit": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/unit",
|
|
145
|
-
"test:integration": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/integration",
|
|
146
|
-
"test:e2e": "NODE_OPTIONS=--experimental-vm-modules npx jest tests/e2e",
|
|
147
|
-
"scan:issues": "node deep-scan-issues.cjs",
|
|
148
|
-
"dev:pilot-test-api": "turbo run dev --filter=pilot-test-api",
|
|
149
|
-
"start:pilot-test-api": "turbo run start --filter=pilot-test-api",
|
|
150
|
-
"dev:pilot-test-web": "turbo run dev --filter=pilot-test-web",
|
|
151
|
-
"start:pilot-test-web": "turbo run start --filter=pilot-test-web",
|
|
152
|
-
"dev:integration-test-api": "turbo run dev --filter=integration-test-api",
|
|
153
|
-
"start:integration-test-api": "turbo run start --filter=integration-test-api",
|
|
154
|
-
"dev:test-gen-api-api": "turbo run dev --filter=test-gen-api-api",
|
|
155
|
-
"start:test-gen-api-api": "turbo run start --filter=test-gen-api-api",
|
|
156
|
-
"dev:cleanup-test-api": "turbo run dev --filter=cleanup-test-api",
|
|
157
|
-
"start:cleanup-test-api": "turbo run start --filter=cleanup-test-api",
|
|
158
|
-
"dev:auth-integration-test-api": "turbo run dev --filter=auth-integration-test-api",
|
|
159
|
-
"start:auth-integration-test-api": "turbo run start --filter=auth-integration-test-api",
|
|
160
|
-
"dev:e2e-test-api": "turbo run dev --filter=e2e-test-api",
|
|
161
|
-
"start:e2e-test-api": "turbo run start --filter=e2e-test-api"
|
|
162
|
-
}
|
|
163
|
-
}
|
|
171
|
+
"packageManager": "pnpm@10.0.0"
|
|
172
|
+
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
# 🚨 STRICT LOGGING POLICY - MANDATORY
|
|
2
|
-
|
|
3
|
-
## ❌ FORBIDDEN - NEVER USE THESE
|
|
4
|
-
|
|
5
|
-
```javascript
|
|
6
|
-
// ❌ STRICTLY FORBIDDEN - DO NOT USE!
|
|
7
|
-
console.log()
|
|
8
|
-
console.warn()
|
|
9
|
-
console.error()
|
|
10
|
-
console.info()
|
|
11
|
-
console.debug()
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
**VIOLATION OF THIS RULE WILL BE REJECTED IMMEDIATELY!**
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## ✅ CORRECT LOGGING METHODS
|
|
19
|
-
|
|
20
|
-
### Backend (API) - Use Vasuzex Log Facade
|
|
21
|
-
|
|
22
|
-
```javascript
|
|
23
|
-
import { Log } from 'vasuzex';
|
|
24
|
-
|
|
25
|
-
// Info logging
|
|
26
|
-
Log.info('User logged in', { userId: user.id });
|
|
27
|
-
|
|
28
|
-
// Warning logging
|
|
29
|
-
Log.warning('Rate limit approaching', { ip: req.ip, count: 95 });
|
|
30
|
-
|
|
31
|
-
// Error logging
|
|
32
|
-
Log.error('Database connection failed', { error: err.message });
|
|
33
|
-
|
|
34
|
-
// Debug logging (development only)
|
|
35
|
-
Log.debug('Processing order', { orderId: 123, items: 5 });
|
|
36
|
-
|
|
37
|
-
// Critical errors
|
|
38
|
-
Log.critical('Payment gateway down', { gateway: 'razorpay' });
|
|
39
|
-
|
|
40
|
-
// Alerts (requires immediate action)
|
|
41
|
-
Log.alert('Disk space critical', { available: '5%' });
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Frontend (Web) - Use Custom Logger Utility
|
|
45
|
-
|
|
46
|
-
```javascript
|
|
47
|
-
import { logger } from '@/utils/logger';
|
|
48
|
-
|
|
49
|
-
// Info logging (development only)
|
|
50
|
-
logger.info('Config loaded', { apiUrl, mediaUrl });
|
|
51
|
-
|
|
52
|
-
// Warning logging
|
|
53
|
-
logger.warning('API rate limit warning', { remaining: 10 });
|
|
54
|
-
|
|
55
|
-
// Error logging (always logged)
|
|
56
|
-
logger.error('Failed to fetch data', error);
|
|
57
|
-
|
|
58
|
-
// Debug logging (development only)
|
|
59
|
-
logger.debug('Component mounted', { props });
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## 📁 Logger Implementation
|
|
65
|
-
|
|
66
|
-
### Backend: Vasuzex Log Facade
|
|
67
|
-
|
|
68
|
-
**Location:** `vasuzex-v2/framework/Support/Facades/Log.js`
|
|
69
|
-
|
|
70
|
-
**Methods:**
|
|
71
|
-
- `Log.emergency()` - System unusable
|
|
72
|
-
- `Log.alert()` - Immediate action required
|
|
73
|
-
- `Log.critical()` - Critical conditions
|
|
74
|
-
- `Log.error()` - Runtime errors
|
|
75
|
-
- `Log.warning()` - Exceptional but not errors
|
|
76
|
-
- `Log.notice()` - Normal but significant
|
|
77
|
-
- `Log.info()` - Interesting events
|
|
78
|
-
- `Log.debug()` - Debug information
|
|
79
|
-
|
|
80
|
-
**Configuration:** `config/logging.cjs`
|
|
81
|
-
|
|
82
|
-
### Frontend: Custom Logger Utility
|
|
83
|
-
|
|
84
|
-
**Location:** `apps/customer/web/src/utils/logger.js`
|
|
85
|
-
|
|
86
|
-
**Features:**
|
|
87
|
-
- Automatic timestamp
|
|
88
|
-
- Context serialization
|
|
89
|
-
- Development-only info/debug logs
|
|
90
|
-
- Always-on error logs
|
|
91
|
-
- Prefix: `[neasto]`
|
|
92
|
-
|
|
93
|
-
**Methods:**
|
|
94
|
-
- `logger.info(message, context)` - Development only
|
|
95
|
-
- `logger.warning(message, context)` - Development/Test
|
|
96
|
-
- `logger.error(message, error)` - Always logged
|
|
97
|
-
- `logger.debug(message, data)` - Development only
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## 🔍 Examples
|
|
102
|
-
|
|
103
|
-
### ✅ CORRECT
|
|
104
|
-
|
|
105
|
-
```javascript
|
|
106
|
-
// Backend
|
|
107
|
-
import { Log } from 'vasuzex';
|
|
108
|
-
|
|
109
|
-
async function sendOTP(phone) {
|
|
110
|
-
Log.info(`OTP sent to ${phone}`);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async function processPayment(orderId) {
|
|
114
|
-
try {
|
|
115
|
-
// ... payment logic
|
|
116
|
-
Log.info('Payment processed', { orderId, amount });
|
|
117
|
-
} catch (error) {
|
|
118
|
-
Log.error('Payment failed', { orderId, error: error.message });
|
|
119
|
-
throw error;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Frontend
|
|
124
|
-
import { logger } from '@/utils/logger';
|
|
125
|
-
|
|
126
|
-
function LoginForm() {
|
|
127
|
-
const handleLogin = async () => {
|
|
128
|
-
try {
|
|
129
|
-
logger.debug('Login attempt', { phone });
|
|
130
|
-
const result = await authService.login(phone);
|
|
131
|
-
logger.info('Login successful');
|
|
132
|
-
} catch (error) {
|
|
133
|
-
logger.error('Login failed', error);
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
### ❌ WRONG
|
|
140
|
-
|
|
141
|
-
```javascript
|
|
142
|
-
// ❌ NEVER DO THIS!
|
|
143
|
-
console.log('User logged in');
|
|
144
|
-
console.error('Failed to process');
|
|
145
|
-
console.warn('Rate limit warning');
|
|
146
|
-
|
|
147
|
-
// ❌ NEVER DO THIS IN PRODUCTION CODE!
|
|
148
|
-
if (isDevelopment) {
|
|
149
|
-
console.log('Debug info'); // Still wrong! Use logger
|
|
150
|
-
}
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## 📋 Migration Checklist
|
|
156
|
-
|
|
157
|
-
When adding new code:
|
|
158
|
-
|
|
159
|
-
- [ ] Import `Log` from `vasuzex` (backend)
|
|
160
|
-
- [ ] Import `logger` from `@/utils/logger` (frontend)
|
|
161
|
-
- [ ] NO direct console.* calls anywhere
|
|
162
|
-
- [ ] Use appropriate log level (info/warning/error/debug)
|
|
163
|
-
- [ ] Include context objects for debugging
|
|
164
|
-
- [ ] Test logging in development mode
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## 🔧 Current Status
|
|
169
|
-
|
|
170
|
-
### Backend Files Using Log Facade ✅
|
|
171
|
-
|
|
172
|
-
- `apps/customer/api/src/services/AuthService.js`
|
|
173
|
-
- `apps/customer/api/src/services/OrderModificationService.js`
|
|
174
|
-
|
|
175
|
-
### Frontend Files Using Logger ✅
|
|
176
|
-
|
|
177
|
-
- `apps/customer/web/src/hooks/useAuth.js`
|
|
178
|
-
- `apps/customer/web/src/components/auth/LoginForm.jsx`
|
|
179
|
-
- `apps/customer/web/src/App.jsx`
|
|
180
|
-
- `apps/customer/web/src/lib/AppConfigProvider.jsx`
|
|
181
|
-
|
|
182
|
-
### Cleaned Files (No Logging) ✅
|
|
183
|
-
|
|
184
|
-
- `apps/customer/web/src/main.jsx`
|
|
185
|
-
- `apps/customer/web/src/lib/api-client.js`
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## ⚠️ REMEMBER
|
|
190
|
-
|
|
191
|
-
**NEVER write `console.log`, `console.warn`, or `console.error` in any file!**
|
|
192
|
-
|
|
193
|
-
**ALWAYS use:**
|
|
194
|
-
- Backend: `Log.info()`, `Log.error()`, `Log.warning()`, `Log.debug()`
|
|
195
|
-
- Frontend: `logger.info()`, `logger.error()`, `logger.warning()`, `logger.debug()`
|
|
196
|
-
|
|
197
|
-
**This is not a suggestion - it's a strict requirement!**
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
Last Updated: 2025-12-10
|