create-fullstack-boilerplate 2.1.10 → 2.2.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/README.md +6 -6
- package/index.js +1 -141
- package/lib/addDB.js +0 -2
- package/lib/addRoute.js +4 -6
- package/lib/copyProject.js +0 -1
- package/lib/prompts.js +10 -10
- package/lib/setupExtraDB.js +87 -89
- package/lib/testDBConnection.js +1 -35
- package/lib/utils.js +1 -130
- package/package.json +86 -46
- package/template/Frontend/package-lock.json +421 -63
- package/template/Frontend/package.json +2 -1
- package/template/Frontend/src/App.jsx +2 -0
- package/template/Frontend/src/config/routes.js +9 -1
- package/template/Frontend/src/pages/Architecture.jsx +137 -0
- package/template/Frontend/src/pages/Dashboard.jsx +503 -116
- package/lib/assertDependency.js +0 -14
- package/lib/ensureDir.js +0 -7
- package/lib/installDeps.js +0 -11
- package/lib/runInstall.js +0 -10
|
@@ -1,135 +1,522 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
1
|
import { useTheme } from '../contexts/ThemeContext';
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import ReactFlow, {
|
|
3
|
+
Background,
|
|
4
|
+
Controls,
|
|
5
|
+
MiniMap,
|
|
6
|
+
useNodesState,
|
|
7
|
+
useEdgesState,
|
|
8
|
+
} from 'reactflow';
|
|
9
|
+
import 'reactflow/dist/style.css';
|
|
5
10
|
|
|
6
11
|
const Dashboard = () => {
|
|
7
12
|
const { isDark } = useTheme();
|
|
8
|
-
const [sections, setSections] = useState([]);
|
|
9
|
-
const [loading, setLoading] = useState(false);
|
|
10
|
-
const [error, setError] = useState(null);
|
|
11
|
-
|
|
12
|
-
const fetchDashboardInfo = async () => {
|
|
13
|
-
setLoading(true);
|
|
14
|
-
try {
|
|
15
|
-
const response = await axiosDashboardClient.get('getDashboardHealth');
|
|
16
|
-
setSections(response.data);
|
|
17
|
-
} catch (err) {
|
|
18
|
-
setError(err.message);
|
|
19
|
-
} finally {
|
|
20
|
-
setLoading(false);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
fetchDashboardInfo();
|
|
26
|
-
}, []);
|
|
27
13
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
const initialNodes = [
|
|
15
|
+
// Row 1: Frontend Entry & Setup
|
|
16
|
+
{
|
|
17
|
+
id: 'browser',
|
|
18
|
+
type: 'input',
|
|
19
|
+
data: { label: '🌐 User Interaction\nBrowser Request' },
|
|
20
|
+
position: { x: 50, y: 20 },
|
|
21
|
+
style: {
|
|
22
|
+
background: isDark ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' : 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
23
|
+
color: '#fff',
|
|
24
|
+
border: '2px solid #4c51bf',
|
|
25
|
+
borderRadius: '12px',
|
|
26
|
+
padding: '20px',
|
|
27
|
+
fontSize: '16px',
|
|
28
|
+
fontWeight: '600',
|
|
29
|
+
width: 200,
|
|
30
|
+
minHeight: '90px',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'app',
|
|
35
|
+
data: { label: '📱 App.jsx\nApplication Root\nMounts Providers' },
|
|
36
|
+
position: { x: 300, y: 20 },
|
|
37
|
+
style: {
|
|
38
|
+
background: isDark ? '#1e293b' : '#f8fafc',
|
|
39
|
+
color: isDark ? '#e2e8f0' : '#334155',
|
|
40
|
+
border: `2px solid ${isDark ? '#475569' : '#cbd5e1'}`,
|
|
41
|
+
borderRadius: '12px',
|
|
42
|
+
padding: '18px',
|
|
43
|
+
fontSize: '15px',
|
|
44
|
+
fontWeight: '500',
|
|
45
|
+
width: 200,
|
|
46
|
+
minHeight: '90px',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'providers',
|
|
51
|
+
data: { label: '🔧 Context Providers\nAuth + Theme State\nWraps All Components' },
|
|
52
|
+
position: { x: 550, y: 20 },
|
|
53
|
+
style: {
|
|
54
|
+
background: isDark ? '#1e293b' : '#f8fafc',
|
|
55
|
+
color: isDark ? '#e2e8f0' : '#334155',
|
|
56
|
+
border: `2px solid ${isDark ? '#475569' : '#cbd5e1'}`,
|
|
57
|
+
borderRadius: '12px',
|
|
58
|
+
padding: '18px',
|
|
59
|
+
fontSize: '14px',
|
|
60
|
+
fontWeight: '500',
|
|
61
|
+
width: 200,
|
|
62
|
+
minHeight: '90px',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'router',
|
|
67
|
+
data: { label: '🛣️ React Router\nRoute Matching\nURL → Component' },
|
|
68
|
+
position: { x: 800, y: 20 },
|
|
69
|
+
style: {
|
|
70
|
+
background: isDark ? '#1e293b' : '#f8fafc',
|
|
71
|
+
color: isDark ? '#e2e8f0' : '#334155',
|
|
72
|
+
border: `2px solid ${isDark ? '#475569' : '#cbd5e1'}`,
|
|
73
|
+
borderRadius: '12px',
|
|
74
|
+
padding: '18px',
|
|
75
|
+
fontSize: '14px',
|
|
76
|
+
fontWeight: '500',
|
|
77
|
+
width: 200,
|
|
78
|
+
minHeight: '90px',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'protected',
|
|
83
|
+
data: { label: '🛡️ ProtectedRoute\nAuth Verification\nRedirect if Not Logged' },
|
|
84
|
+
position: { x: 1050, y: 20 },
|
|
85
|
+
style: {
|
|
86
|
+
background: isDark ? '#422006' : '#fef3c7',
|
|
87
|
+
color: isDark ? '#fbbf24' : '#92400e',
|
|
88
|
+
border: `2px solid ${isDark ? '#f59e0b' : '#fbbf24'}`,
|
|
89
|
+
borderRadius: '12px',
|
|
90
|
+
padding: '18px',
|
|
91
|
+
fontSize: '13px',
|
|
92
|
+
fontWeight: '500',
|
|
93
|
+
width: 200,
|
|
94
|
+
minHeight: '90px',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'layout',
|
|
99
|
+
data: { label: '📐 Layout Component\nRenders Sidebar\nPage Structure' },
|
|
100
|
+
position: { x: 1300, y: 20 },
|
|
101
|
+
style: {
|
|
102
|
+
background: isDark ? '#0f172a' : '#fff',
|
|
103
|
+
color: isDark ? '#94a3b8' : '#64748b',
|
|
104
|
+
border: `2px solid ${isDark ? '#334155' : '#e2e8f0'}`,
|
|
105
|
+
borderRadius: '12px',
|
|
106
|
+
padding: '18px',
|
|
107
|
+
fontSize: '14px',
|
|
108
|
+
width: 200,
|
|
109
|
+
minHeight: '90px',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'sidebar',
|
|
114
|
+
data: { label: '📋 Sidebar\nNavigation Links\nRoute Selection' },
|
|
115
|
+
position: { x: 1300, y: 160 },
|
|
116
|
+
style: {
|
|
117
|
+
background: isDark ? '#0f172a' : '#fff',
|
|
118
|
+
color: isDark ? '#94a3b8' : '#64748b',
|
|
119
|
+
border: `2px solid ${isDark ? '#334155' : '#e2e8f0'}`,
|
|
120
|
+
borderRadius: '12px',
|
|
121
|
+
padding: '18px',
|
|
122
|
+
fontSize: '13px',
|
|
123
|
+
width: 200,
|
|
124
|
+
minHeight: '80px',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'pages',
|
|
129
|
+
data: { label: '📄 Page Components\nDashboard/Settings\nRender UI + Logic' },
|
|
130
|
+
position: { x: 1550, y: 20 },
|
|
131
|
+
style: {
|
|
132
|
+
background: isDark ? '#0f172a' : '#fff',
|
|
133
|
+
color: isDark ? '#94a3b8' : '#64748b',
|
|
134
|
+
border: `2px solid ${isDark ? '#334155' : '#e2e8f0'}`,
|
|
135
|
+
borderRadius: '12px',
|
|
136
|
+
padding: '18px',
|
|
137
|
+
fontSize: '14px',
|
|
138
|
+
width: 200,
|
|
139
|
+
minHeight: '90px',
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Row 2: API & Encryption Layer
|
|
144
|
+
{
|
|
145
|
+
id: 'encryption',
|
|
146
|
+
data: { label: '🔒 CryptoJS Encrypt\nEncrypt Credentials\nBefore API Call' },
|
|
147
|
+
position: { x: 1050, y: 300 },
|
|
148
|
+
style: {
|
|
149
|
+
background: isDark ? '#134e4a' : '#ccfbf1',
|
|
150
|
+
color: isDark ? '#5eead4' : '#115e59',
|
|
151
|
+
border: `2px solid ${isDark ? '#14b8a6' : '#5eead4'}`,
|
|
152
|
+
borderRadius: '12px',
|
|
153
|
+
padding: '18px',
|
|
154
|
+
fontSize: '13px',
|
|
155
|
+
width: 200,
|
|
156
|
+
minHeight: '80px',
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'axios',
|
|
161
|
+
data: { label: '🌐 Axios Instances\nAPI Client Setup\nBase URL + Config' },
|
|
162
|
+
position: { x: 1550, y: 160 },
|
|
163
|
+
style: {
|
|
164
|
+
background: isDark ? '#134e4a' : '#ccfbf1',
|
|
165
|
+
color: isDark ? '#5eead4' : '#115e59',
|
|
166
|
+
border: `2px solid ${isDark ? '#14b8a6' : '#5eead4'}`,
|
|
167
|
+
borderRadius: '12px',
|
|
168
|
+
padding: '18px',
|
|
169
|
+
fontSize: '13px',
|
|
170
|
+
width: 200,
|
|
171
|
+
minHeight: '80px',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: 'interceptors',
|
|
176
|
+
data: { label: '⚙️ Request Interceptors\nAttach JWT Token\nHandle 401 Errors' },
|
|
177
|
+
position: { x: 1550, y: 300 },
|
|
178
|
+
style: {
|
|
179
|
+
background: isDark ? '#134e4a' : '#ccfbf1',
|
|
180
|
+
color: isDark ? '#5eead4' : '#115e59',
|
|
181
|
+
border: `2px solid ${isDark ? '#14b8a6' : '#5eead4'}`,
|
|
182
|
+
borderRadius: '12px',
|
|
183
|
+
padding: '18px',
|
|
184
|
+
fontSize: '13px',
|
|
185
|
+
width: 200,
|
|
186
|
+
minHeight: '80px',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
// Row 3: Backend Entry & Routing
|
|
191
|
+
{
|
|
192
|
+
id: 'backend',
|
|
193
|
+
data: { label: '🖥️ Express Server\nEntry Point\nserver.js' },
|
|
194
|
+
position: { x: 50, y: 480 },
|
|
195
|
+
style: {
|
|
196
|
+
background: isDark ? 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)' : 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
|
|
197
|
+
color: '#fff',
|
|
198
|
+
border: '2px solid #ec4899',
|
|
199
|
+
borderRadius: '12px',
|
|
200
|
+
padding: '20px',
|
|
201
|
+
fontSize: '16px',
|
|
202
|
+
fontWeight: '600',
|
|
203
|
+
width: 200,
|
|
204
|
+
minHeight: '90px',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
id: 'mainRouter',
|
|
209
|
+
data: { label: '🔀 Main API Router\nRoute Distribution\napp.use("/api", ...)' },
|
|
210
|
+
position: { x: 300, y: 480 },
|
|
211
|
+
style: {
|
|
212
|
+
background: isDark ? '#1e1b4b' : '#f5f3ff',
|
|
213
|
+
color: isDark ? '#c4b5fd' : '#5b21b6',
|
|
214
|
+
border: `2px solid ${isDark ? '#6366f1' : '#c4b5fd'}`,
|
|
215
|
+
borderRadius: '12px',
|
|
216
|
+
padding: '18px',
|
|
217
|
+
fontSize: '14px',
|
|
218
|
+
width: 200,
|
|
219
|
+
minHeight: '90px',
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
id: 'authMiddleware',
|
|
224
|
+
data: { label: '🛡️ Auth Middleware\nVerify JWT Token\nProtect Routes' },
|
|
225
|
+
position: { x: 550, y: 340 },
|
|
226
|
+
style: {
|
|
227
|
+
background: isDark ? '#422006' : '#fef3c7',
|
|
228
|
+
color: isDark ? '#fbbf24' : '#92400e',
|
|
229
|
+
border: `2px solid ${isDark ? '#f59e0b' : '#fbbf24'}`,
|
|
230
|
+
borderRadius: '12px',
|
|
231
|
+
padding: '18px',
|
|
232
|
+
fontSize: '13px',
|
|
233
|
+
fontWeight: '500',
|
|
234
|
+
width: 200,
|
|
235
|
+
minHeight: '80px',
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
id: 'authRoutes',
|
|
240
|
+
data: { label: '🔑 Auth Routes\n/api/auth/*\nLogin/Register/Logout' },
|
|
241
|
+
position: { x: 550, y: 480 },
|
|
242
|
+
style: {
|
|
243
|
+
background: isDark ? '#18181b' : '#fafafa',
|
|
244
|
+
color: isDark ? '#a1a1aa' : '#52525b',
|
|
245
|
+
border: `2px solid ${isDark ? '#52525b' : '#d4d4d8'}`,
|
|
246
|
+
borderRadius: '12px',
|
|
247
|
+
padding: '18px',
|
|
248
|
+
fontSize: '13px',
|
|
249
|
+
width: 200,
|
|
250
|
+
minHeight: '90px',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: 'dashRoutes',
|
|
255
|
+
data: { label: '📊 Dashboard Routes\n/api/dash/*\nGet Dashboard Data' },
|
|
256
|
+
position: { x: 800, y: 480 },
|
|
257
|
+
style: {
|
|
258
|
+
background: isDark ? '#18181b' : '#fafafa',
|
|
259
|
+
color: isDark ? '#a1a1aa' : '#52525b',
|
|
260
|
+
border: `2px solid ${isDark ? '#52525b' : '#d4d4d8'}`,
|
|
261
|
+
borderRadius: '12px',
|
|
262
|
+
padding: '18px',
|
|
263
|
+
fontSize: '13px',
|
|
264
|
+
width: 200,
|
|
265
|
+
minHeight: '90px',
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
id: 'settingsRoutes',
|
|
270
|
+
data: { label: '⚙️ Settings Routes\n/api/settings/*\nUpdate User Settings' },
|
|
271
|
+
position: { x: 1050, y: 480 },
|
|
272
|
+
style: {
|
|
273
|
+
background: isDark ? '#18181b' : '#fafafa',
|
|
274
|
+
color: isDark ? '#a1a1aa' : '#52525b',
|
|
275
|
+
border: `2px solid ${isDark ? '#52525b' : '#d4d4d8'}`,
|
|
276
|
+
borderRadius: '12px',
|
|
277
|
+
padding: '18px',
|
|
278
|
+
fontSize: '13px',
|
|
279
|
+
width: 200,
|
|
280
|
+
minHeight: '90px',
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
// Row 4: Business Logic Services
|
|
285
|
+
{
|
|
286
|
+
id: 'cryptoService',
|
|
287
|
+
data: { label: '🔓 Crypto Service\nDecrypt Credentials\nCryptoJS Decrypt' },
|
|
288
|
+
position: { x: 300, y: 620 },
|
|
289
|
+
style: {
|
|
290
|
+
background: isDark ? '#422006' : '#fef3c7',
|
|
291
|
+
color: isDark ? '#fbbf24' : '#92400e',
|
|
292
|
+
border: `2px solid ${isDark ? '#f59e0b' : '#fbbf24'}`,
|
|
293
|
+
borderRadius: '12px',
|
|
294
|
+
padding: '18px',
|
|
295
|
+
fontSize: '13px',
|
|
296
|
+
width: 200,
|
|
297
|
+
minHeight: '80px',
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
id: 'authService',
|
|
302
|
+
data: { label: '🔐 Auth Service\nBcrypt Password Hash\nJWT Token Generation' },
|
|
303
|
+
position: { x: 550, y: 620 },
|
|
304
|
+
style: {
|
|
305
|
+
background: isDark ? '#1c1917' : '#fafaf9',
|
|
306
|
+
color: isDark ? '#d6d3d1' : '#57534e',
|
|
307
|
+
border: `2px solid ${isDark ? '#78716c' : '#d6d3d1'}`,
|
|
308
|
+
borderRadius: '12px',
|
|
309
|
+
padding: '18px',
|
|
310
|
+
fontSize: '13px',
|
|
311
|
+
width: 200,
|
|
312
|
+
minHeight: '80px',
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: 'dashService',
|
|
317
|
+
data: { label: '📊 Dashboard Service\nBusiness Logic\nData Processing' },
|
|
318
|
+
position: { x: 800, y: 620 },
|
|
319
|
+
style: {
|
|
320
|
+
background: isDark ? '#1c1917' : '#fafaf9',
|
|
321
|
+
color: isDark ? '#d6d3d1' : '#57534e',
|
|
322
|
+
border: `2px solid ${isDark ? '#78716c' : '#d6d3d1'}`,
|
|
323
|
+
borderRadius: '12px',
|
|
324
|
+
padding: '18px',
|
|
325
|
+
fontSize: '13px',
|
|
326
|
+
width: 200,
|
|
327
|
+
minHeight: '80px',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: 'settingsService',
|
|
332
|
+
data: { label: '⚙️ Settings Service\nBusiness Logic\nUpdate Operations' },
|
|
333
|
+
position: { x: 1050, y: 620 },
|
|
334
|
+
style: {
|
|
335
|
+
background: isDark ? '#1c1917' : '#fafaf9',
|
|
336
|
+
color: isDark ? '#d6d3d1' : '#57534e',
|
|
337
|
+
border: `2px solid ${isDark ? '#78716c' : '#d6d3d1'}`,
|
|
338
|
+
borderRadius: '12px',
|
|
339
|
+
padding: '18px',
|
|
340
|
+
fontSize: '13px',
|
|
341
|
+
width: 200,
|
|
342
|
+
minHeight: '80px',
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
|
|
346
|
+
// Row 5: Database Layer
|
|
347
|
+
{
|
|
348
|
+
id: 'models',
|
|
349
|
+
data: { label: '📦 Sequelize Models\nORM Definitions\nUser/Post/etc Tables' },
|
|
350
|
+
position: { x: 1300, y: 620 },
|
|
351
|
+
style: {
|
|
352
|
+
background: isDark ? 'linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%)' : 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
353
|
+
color: '#fff',
|
|
354
|
+
border: '2px solid #4c51bf',
|
|
355
|
+
borderRadius: '12px',
|
|
356
|
+
padding: '20px',
|
|
357
|
+
fontSize: '14px',
|
|
358
|
+
fontWeight: '600',
|
|
359
|
+
width: 200,
|
|
360
|
+
minHeight: '90px',
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: 'dbConfig',
|
|
365
|
+
data: { label: '⚙️ DB Config\nConnection Settings\ndbConfigs.js' },
|
|
366
|
+
position: { x: 1300, y: 480 },
|
|
367
|
+
style: {
|
|
368
|
+
background: isDark ? '#171717' : '#f5f5f5',
|
|
369
|
+
color: isDark ? '#a3a3a3' : '#525252',
|
|
370
|
+
border: `2px solid ${isDark ? '#525252' : '#a3a3a3'}`,
|
|
371
|
+
borderRadius: '12px',
|
|
372
|
+
padding: '18px',
|
|
373
|
+
fontSize: '13px',
|
|
374
|
+
width: 200,
|
|
375
|
+
minHeight: '80px',
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
id: 'dbInit',
|
|
380
|
+
data: { label: '🚀 DB Initialization\nConnect + Sync\nRun on Server Start' },
|
|
381
|
+
position: { x: 50, y: 620 },
|
|
382
|
+
style: {
|
|
383
|
+
background: isDark ? '#171717' : '#f5f5f5',
|
|
384
|
+
color: isDark ? '#a3a3a3' : '#525252',
|
|
385
|
+
border: `2px solid ${isDark ? '#525252' : '#a3a3a3'}`,
|
|
386
|
+
borderRadius: '12px',
|
|
387
|
+
padding: '18px',
|
|
388
|
+
fontSize: '13px',
|
|
389
|
+
width: 200,
|
|
390
|
+
minHeight: '80px',
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
id: 'database',
|
|
395
|
+
type: 'output',
|
|
396
|
+
data: { label: '💾 Database\nPostgres/MySQL\nPersistent Storage' },
|
|
397
|
+
position: { x: 1550, y: 620 },
|
|
398
|
+
style: {
|
|
399
|
+
background: isDark ? 'linear-gradient(135deg, #134e4a 0%, #065f46 100%)' : 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
|
|
400
|
+
color: '#fff',
|
|
401
|
+
border: '2px solid #059669',
|
|
402
|
+
borderRadius: '12px',
|
|
403
|
+
padding: '20px',
|
|
404
|
+
fontSize: '16px',
|
|
405
|
+
fontWeight: '600',
|
|
406
|
+
width: 200,
|
|
407
|
+
minHeight: '90px',
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
];
|
|
411
|
+
|
|
412
|
+
const initialEdges = [
|
|
413
|
+
// ===== FRONTEND FLOW =====
|
|
414
|
+
// Main component hierarchy flow
|
|
415
|
+
{ id: 'e1', source: 'browser', target: 'app', animated: true, style: { stroke: '#667eea', strokeWidth: 3 }, label: 'Load App' },
|
|
416
|
+
{ id: 'e2', source: 'app', target: 'providers', animated: true, style: { stroke: '#667eea', strokeWidth: 3 }, label: 'Mount' },
|
|
417
|
+
{ id: 'e3', source: 'providers', target: 'router', animated: true, style: { stroke: '#667eea', strokeWidth: 3 }, label: 'Wrap' },
|
|
418
|
+
{ id: 'e4', source: 'router', target: 'protected', animated: true, style: { stroke: '#667eea', strokeWidth: 3 }, label: 'Route' },
|
|
419
|
+
{ id: 'e5', source: 'protected', target: 'layout', animated: true, style: { stroke: '#f59e0b', strokeWidth: 3 }, label: 'Auth ✓' },
|
|
420
|
+
{ id: 'e6', source: 'layout', target: 'sidebar', style: { stroke: '#94a3b8', strokeWidth: 2 }, label: 'Contains' },
|
|
421
|
+
{ id: 'e7', source: 'layout', target: 'pages', animated: true, style: { stroke: '#667eea', strokeWidth: 3 }, label: 'Render' },
|
|
422
|
+
|
|
423
|
+
// Sidebar navigation
|
|
424
|
+
{ id: 'e8', source: 'sidebar', target: 'pages', style: { stroke: '#94a3b8', strokeWidth: 2 }, label: 'Navigate', type: 'smoothstep' },
|
|
425
|
+
|
|
426
|
+
// ===== API CALL FLOW =====
|
|
427
|
+
// Pages to Axios
|
|
428
|
+
{ id: 'e9', source: 'pages', target: 'axios', animated: true, style: { stroke: '#14b8a6', strokeWidth: 3 }, label: 'API Call' },
|
|
429
|
+
{ id: 'e10', source: 'axios', target: 'interceptors', animated: true, style: { stroke: '#14b8a6', strokeWidth: 3 }, label: 'Process' },
|
|
430
|
+
|
|
431
|
+
// Encryption flow (for login/register)
|
|
432
|
+
{ id: 'e11', source: 'protected', target: 'encryption', style: { stroke: '#14b8a6', strokeWidth: 2 }, label: 'Encrypt Data', type: 'smoothstep' },
|
|
433
|
+
{ id: 'e12', source: 'encryption', target: 'axios', style: { stroke: '#14b8a6', strokeWidth: 2 }, label: 'Encrypted', type: 'smoothstep' },
|
|
434
|
+
|
|
435
|
+
// Interceptors to Backend
|
|
436
|
+
{ id: 'e13', source: 'interceptors', target: 'backend', animated: true, style: { stroke: '#ec4899', strokeWidth: 4 }, label: 'HTTP Request', type: 'smoothstep' },
|
|
437
|
+
|
|
438
|
+
// ===== BACKEND FLOW =====
|
|
439
|
+
// Server initialization
|
|
440
|
+
{ id: 'e14', source: 'backend', target: 'dbInit', style: { stroke: '#525252', strokeWidth: 2 }, label: 'Initialize', type: 'smoothstep' },
|
|
441
|
+
{ id: 'e15', source: 'backend', target: 'mainRouter', animated: true, style: { stroke: '#ec4899', strokeWidth: 3 }, label: 'Route to /api' },
|
|
31
442
|
|
|
32
|
-
|
|
33
|
-
|
|
443
|
+
// Main Router distribution
|
|
444
|
+
{ id: 'e16', source: 'mainRouter', target: 'authRoutes', animated: true, style: { stroke: '#6366f1', strokeWidth: 3 }, label: '/auth' },
|
|
445
|
+
{ id: 'e17', source: 'mainRouter', target: 'dashRoutes', animated: true, style: { stroke: '#6366f1', strokeWidth: 3 }, label: '/dash' },
|
|
446
|
+
{ id: 'e18', source: 'mainRouter', target: 'settingsRoutes', animated: true, style: { stroke: '#6366f1', strokeWidth: 3 }, label: '/settings' },
|
|
34
447
|
|
|
448
|
+
// Auth Middleware checks
|
|
449
|
+
{ id: 'e19', source: 'mainRouter', target: 'authMiddleware', style: { stroke: '#f59e0b', strokeWidth: 2 }, label: 'Check Auth' },
|
|
450
|
+
{ id: 'e20', source: 'authMiddleware', target: 'dashRoutes', style: { stroke: '#f59e0b', strokeWidth: 2 }, label: 'Authorize', type: 'smoothstep' },
|
|
451
|
+
{ id: 'e21', source: 'authMiddleware', target: 'settingsRoutes', style: { stroke: '#f59e0b', strokeWidth: 2 }, label: 'Authorize', type: 'smoothstep' },
|
|
452
|
+
|
|
453
|
+
// ===== SERVICES LAYER =====
|
|
454
|
+
// Routes to Services
|
|
455
|
+
{ id: 'e22', source: 'authRoutes', target: 'cryptoService', style: { stroke: '#f59e0b', strokeWidth: 2 }, label: 'Decrypt' },
|
|
456
|
+
{ id: 'e23', source: 'cryptoService', target: 'authService', animated: true, style: { stroke: '#78716c', strokeWidth: 3 }, label: 'Process' },
|
|
457
|
+
{ id: 'e24', source: 'authRoutes', target: 'authService', animated: true, style: { stroke: '#78716c', strokeWidth: 3 }, label: 'Handle' },
|
|
458
|
+
{ id: 'e25', source: 'dashRoutes', target: 'dashService', animated: true, style: { stroke: '#78716c', strokeWidth: 3 }, label: 'Handle' },
|
|
459
|
+
{ id: 'e26', source: 'settingsRoutes', target: 'settingsService', animated: true, style: { stroke: '#78716c', strokeWidth: 3 }, label: 'Handle' },
|
|
460
|
+
|
|
461
|
+
// ===== DATABASE LAYER =====
|
|
462
|
+
// Services to Models
|
|
463
|
+
{ id: 'e27', source: 'authService', target: 'models', animated: true, style: { stroke: '#4c51bf', strokeWidth: 3 }, label: 'Query' },
|
|
464
|
+
{ id: 'e28', source: 'dashService', target: 'models', animated: true, style: { stroke: '#4c51bf', strokeWidth: 3 }, label: 'Query' },
|
|
465
|
+
{ id: 'e29', source: 'settingsService', target: 'models', animated: true, style: { stroke: '#4c51bf', strokeWidth: 3 }, label: 'Query' },
|
|
466
|
+
|
|
467
|
+
// Models configuration
|
|
468
|
+
{ id: 'e30', source: 'models', target: 'dbConfig', style: { stroke: '#525252', strokeWidth: 2 }, label: 'Use Config' },
|
|
469
|
+
{ id: 'e31', source: 'dbConfig', target: 'database', style: { stroke: '#10b981', strokeWidth: 2 }, label: 'Connect' },
|
|
470
|
+
{ id: 'e32', source: 'models', target: 'database', animated: true, style: { stroke: '#10b981', strokeWidth: 3 }, label: 'Execute SQL' },
|
|
471
|
+
|
|
472
|
+
// DB initialization
|
|
473
|
+
{ id: 'e33', source: 'dbInit', target: 'dbConfig', style: { stroke: '#525252', strokeWidth: 2 }, label: 'Load' },
|
|
474
|
+
{ id: 'e34', source: 'dbInit', target: 'models', style: { stroke: '#525252', strokeWidth: 2 }, label: 'Sync Tables' },
|
|
475
|
+
];
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
const [nodes, , onNodesChange] = useNodesState(initialNodes);
|
|
479
|
+
const [edges, , onEdgesChange] = useEdgesState(initialEdges);
|
|
480
|
+
|
|
481
|
+
return (
|
|
482
|
+
<div className={`min-h-screen transition-colors duration-300 ${isDark ? "bg-[#0a0a0a]" : "bg-[#fafafa]"}`}>
|
|
483
|
+
<div className="h-screen flex flex-col">
|
|
35
484
|
{/* Header */}
|
|
36
|
-
<div className="
|
|
37
|
-
<h1 className={`text-4xl sm:text-5xl font-semibold mb-
|
|
485
|
+
<div className="px-6 py-6">
|
|
486
|
+
<h1 className={`text-4xl sm:text-5xl font-semibold mb-2 tracking-tight
|
|
38
487
|
${isDark ? "text-white" : "text-gray-900"}`}
|
|
39
488
|
style={{ fontFamily: "'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif" }}>
|
|
40
|
-
|
|
489
|
+
Application Flow
|
|
41
490
|
</h1>
|
|
42
491
|
<p className={`text-lg ${isDark ? "text-gray-400" : "text-gray-600"}`}>
|
|
43
|
-
|
|
492
|
+
Interactive visualization of the full-stack architecture
|
|
44
493
|
</p>
|
|
45
494
|
</div>
|
|
46
495
|
|
|
47
|
-
{/*
|
|
48
|
-
{
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
?
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
${isDark
|
|
71
|
-
? "bg-[#141414] border border-gray-800/50 hover:border-gray-700/80"
|
|
72
|
-
: "bg-white border border-gray-200 hover:border-gray-300 shadow-sm hover:shadow-md"}`}
|
|
73
|
-
style={{
|
|
74
|
-
animation: `fadeInUp 0.5s ease-out ${index * 0.1}s both`
|
|
75
|
-
}}>
|
|
76
|
-
|
|
77
|
-
{/* Card Header */}
|
|
78
|
-
<div className={`px-8 py-6 border-b ${isDark ? "border-gray-800/50" : "border-gray-100"}`}>
|
|
79
|
-
<div className="flex items-center gap-4">
|
|
80
|
-
<div className={`flex-shrink-0 w-12 h-12 flex items-center justify-center rounded-xl text-2xl
|
|
81
|
-
${isDark ? "bg-gray-800/80" : "bg-gray-100"}`}>
|
|
82
|
-
{section.icon}
|
|
83
|
-
</div>
|
|
84
|
-
<h2 className={`text-xl font-semibold ${isDark ? "text-gray-100" : "text-gray-900"}`}
|
|
85
|
-
style={{ fontFamily: "'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif" }}>
|
|
86
|
-
{section.title}
|
|
87
|
-
</h2>
|
|
88
|
-
</div>
|
|
89
|
-
</div>
|
|
90
|
-
|
|
91
|
-
{/* Card Content */}
|
|
92
|
-
<div className="px-8 py-6">
|
|
93
|
-
<ul className="space-y-4">
|
|
94
|
-
{section.items.map((item, i) => (
|
|
95
|
-
<li
|
|
96
|
-
key={i}
|
|
97
|
-
className="flex items-start gap-3 group/item">
|
|
98
|
-
<div className={`flex-shrink-0 w-1.5 h-1.5 rounded-full mt-2.5 transition-all duration-200
|
|
99
|
-
${isDark
|
|
100
|
-
? "bg-gray-600 group-hover/item:bg-blue-500"
|
|
101
|
-
: "bg-gray-400 group-hover/item:bg-blue-600"}`}>
|
|
102
|
-
</div>
|
|
103
|
-
<span className={`text-[15px] leading-relaxed transition-colors duration-200
|
|
104
|
-
${isDark
|
|
105
|
-
? "text-gray-400 group-hover/item:text-gray-300"
|
|
106
|
-
: "text-gray-600 group-hover/item:text-gray-900"}`}
|
|
107
|
-
style={{ fontFamily: "'SF Pro Text', -apple-system, BlinkMacSystemFont, sans-serif" }}>
|
|
108
|
-
{item}
|
|
109
|
-
</span>
|
|
110
|
-
</li>
|
|
111
|
-
))}
|
|
112
|
-
</ul>
|
|
113
|
-
</div>
|
|
114
|
-
</div>
|
|
115
|
-
))}
|
|
116
|
-
</div>
|
|
117
|
-
)}
|
|
496
|
+
{/* Flow Diagram */}
|
|
497
|
+
<div className={`flex-1 ${isDark ? 'bg-[#0a0a0a]' : 'bg-white'} rounded-xl mx-6 mb-6 border ${isDark ? 'border-gray-800' : 'border-gray-200'}`}>
|
|
498
|
+
<ReactFlow
|
|
499
|
+
nodes={nodes}
|
|
500
|
+
edges={edges}
|
|
501
|
+
onNodesChange={onNodesChange}
|
|
502
|
+
onEdgesChange={onEdgesChange}
|
|
503
|
+
fitView
|
|
504
|
+
attributionPosition="bottom-left"
|
|
505
|
+
>
|
|
506
|
+
<Background color={isDark ? '#1f2937' : '#e5e7eb'} gap={16} />
|
|
507
|
+
<Controls className={isDark ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} />
|
|
508
|
+
<MiniMap
|
|
509
|
+
nodeColor={(node) => {
|
|
510
|
+
if (node.type === 'input') return '#667eea';
|
|
511
|
+
if (node.type === 'output') return '#10b981';
|
|
512
|
+
return isDark ? '#1e293b' : '#f8fafc';
|
|
513
|
+
}}
|
|
514
|
+
maskColor={isDark ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.6)'}
|
|
515
|
+
className={isDark ? 'bg-gray-900 border-gray-700' : 'bg-gray-50 border-gray-200'}
|
|
516
|
+
/>
|
|
517
|
+
</ReactFlow>
|
|
518
|
+
</div>
|
|
118
519
|
</div>
|
|
119
|
-
|
|
120
|
-
{/* Minimal Animations */}
|
|
121
|
-
<style>{`
|
|
122
|
-
@keyframes fadeInUp {
|
|
123
|
-
from {
|
|
124
|
-
opacity: 0;
|
|
125
|
-
transform: translateY(20px);
|
|
126
|
-
}
|
|
127
|
-
to {
|
|
128
|
-
opacity: 1;
|
|
129
|
-
transform: translateY(0);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
`}</style>
|
|
133
520
|
</div>
|
|
134
521
|
);
|
|
135
522
|
};
|
package/lib/assertDependency.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// const path = require("path");
|
|
2
|
-
|
|
3
|
-
// function assertDependency(depName, cwd) {
|
|
4
|
-
// try {
|
|
5
|
-
// return require(path.join(cwd, "node_modules", depName));
|
|
6
|
-
// } catch (err) {
|
|
7
|
-
// throw new Error(
|
|
8
|
-
// `Dependency '${depName}' is not installed in ${cwd}.\n` +
|
|
9
|
-
// `Run: cd ${cwd} && npm install ${depName}`
|
|
10
|
-
// );
|
|
11
|
-
// }
|
|
12
|
-
// }
|
|
13
|
-
|
|
14
|
-
// module.exports = assertDependency;
|