create-fullstack-boilerplate 1.0.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.
Files changed (71) hide show
  1. package/README.md +390 -0
  2. package/index.js +78 -0
  3. package/lib/addDB.js +77 -0
  4. package/lib/addRoute.js +264 -0
  5. package/lib/copyProject.js +25 -0
  6. package/lib/dataTypes.js +79 -0
  7. package/lib/installDeps.js +11 -0
  8. package/lib/prompts.js +289 -0
  9. package/lib/setupExtraDB.js +172 -0
  10. package/lib/setupMainDB.js +9 -0
  11. package/lib/testDBConnection.js +31 -0
  12. package/lib/utils.js +39 -0
  13. package/package.json +45 -0
  14. package/template/Backend/.env +7 -0
  15. package/template/Backend/DB/DBInit.js +28 -0
  16. package/template/Backend/DB/dbConfigs.js +4 -0
  17. package/template/Backend/Models/index.js +54 -0
  18. package/template/Backend/README.md +535 -0
  19. package/template/Backend/middleware/authMiddleware.js +19 -0
  20. package/template/Backend/package-lock.json +2997 -0
  21. package/template/Backend/package.json +32 -0
  22. package/template/Backend/routes/authRoutes.js +15 -0
  23. package/template/Backend/routes/dashboardRoutes.js +13 -0
  24. package/template/Backend/routes/index.js +15 -0
  25. package/template/Backend/routes/settingsRoutes.js +9 -0
  26. package/template/Backend/server.js +70 -0
  27. package/template/Backend/services/authService.js +68 -0
  28. package/template/Backend/services/cryptoService.js +14 -0
  29. package/template/Backend/services/dashboardService.js +39 -0
  30. package/template/Backend/services/settingsService.js +43 -0
  31. package/template/Frontend/.env +3 -0
  32. package/template/Frontend/README.md +576 -0
  33. package/template/Frontend/eslint.config.js +29 -0
  34. package/template/Frontend/index.html +13 -0
  35. package/template/Frontend/package-lock.json +3690 -0
  36. package/template/Frontend/package.json +39 -0
  37. package/template/Frontend/public/PMDLogo.png +0 -0
  38. package/template/Frontend/public/pp.jpg +0 -0
  39. package/template/Frontend/public/tabicon.png +0 -0
  40. package/template/Frontend/src/App.jsx +71 -0
  41. package/template/Frontend/src/assets/fonts/ArticulatCFDemiBold/font.woff +0 -0
  42. package/template/Frontend/src/assets/fonts/ArticulatCFDemiBold/font.woff2 +0 -0
  43. package/template/Frontend/src/assets/fonts/ArticulatCFNormal/font.woff +0 -0
  44. package/template/Frontend/src/assets/fonts/ArticulatCFNormal/font.woff2 +0 -0
  45. package/template/Frontend/src/assets/fonts/ArticulatCFRegular/font.woff +0 -0
  46. package/template/Frontend/src/assets/fonts/ArticulatCFRegular/font.woff2 +0 -0
  47. package/template/Frontend/src/assets/fonts/MixtaProRegularItalic/font.woff +0 -0
  48. package/template/Frontend/src/assets/fonts/MixtaProRegularItalic/font.woff2 +0 -0
  49. package/template/Frontend/src/assets/fonts/fonts_sohne/OTF/S/303/266hneMono-Buch.otf +0 -0
  50. package/template/Frontend/src/assets/fonts/fonts_sohne/OTF/S/303/266hneMono-Leicht.otf +0 -0
  51. package/template/Frontend/src/assets/fonts/fonts_sohne/WOFF2/soehne-mono-buch.woff2 +0 -0
  52. package/template/Frontend/src/assets/fonts/fonts_sohne/WOFF2/soehne-mono-leicht.woff2 +0 -0
  53. package/template/Frontend/src/components/Layout.jsx +61 -0
  54. package/template/Frontend/src/components/Loader.jsx +19 -0
  55. package/template/Frontend/src/components/ProtectedRoute.jsx +19 -0
  56. package/template/Frontend/src/components/Sidebar.jsx +286 -0
  57. package/template/Frontend/src/components/ThemeToggle.jsx +30 -0
  58. package/template/Frontend/src/config/axiosClient.js +46 -0
  59. package/template/Frontend/src/config/encryption.js +11 -0
  60. package/template/Frontend/src/config/routes.js +65 -0
  61. package/template/Frontend/src/contexts/AuthContext.jsx +144 -0
  62. package/template/Frontend/src/contexts/ThemeContext.jsx +69 -0
  63. package/template/Frontend/src/index.css +88 -0
  64. package/template/Frontend/src/main.jsx +11 -0
  65. package/template/Frontend/src/pages/Dashboard.jsx +137 -0
  66. package/template/Frontend/src/pages/Login.jsx +195 -0
  67. package/template/Frontend/src/pages/NotFound.jsx +70 -0
  68. package/template/Frontend/src/pages/Settings.jsx +69 -0
  69. package/template/Frontend/tailwind.config.js +90 -0
  70. package/template/Frontend/vite.config.js +37 -0
  71. package/template/Readme.md +0 -0
@@ -0,0 +1,535 @@
1
+ # Backend Documentation
2
+
3
+ ## Overview
4
+
5
+ This is the backend of your fullstack application built with **Node.js**, **Express**, and **Sequelize ORM**. It provides a scalable, maintainable structure for building RESTful APIs with multiple database support.
6
+
7
+ ## ๐Ÿ—๏ธ Project Structure
8
+
9
+ ```
10
+ backend/
11
+ โ”œโ”€โ”€ DB/ # Database configurations
12
+ โ”‚ โ”œโ”€โ”€ DBInit.js # Database connection initialization with retry logic
13
+ โ”‚ โ””โ”€โ”€ dbConfigs.js # Array of all database configurations
14
+ โ”œโ”€โ”€ Models/ # Sequelize models organized by database
15
+ โ”‚ โ”œโ”€โ”€ index.js # Exports all database connections
16
+ โ”‚ โ””โ”€โ”€ [DB_NAME]/ # Folder for each database
17
+ โ”‚ โ””โ”€โ”€ [model].js # Individual model files
18
+ โ”œโ”€โ”€ routes/ # API route definitions
19
+ โ”‚ โ”œโ”€โ”€ index.js # Main router that combines all routes
20
+ โ”‚ โ”œโ”€โ”€ authRoutes.js # Authentication endpoints
21
+ โ”‚ โ”œโ”€โ”€ dashboardRoutes.js # Dashboard endpoints
22
+ โ”‚ โ””โ”€โ”€ settingsRoutes.js # Settings endpoints
23
+ โ”œโ”€โ”€ services/ # Business logic layer
24
+ โ”‚ โ”œโ”€โ”€ authService.js # Authentication business logic
25
+ โ”‚ โ”œโ”€โ”€ cryptoService.js # Encryption/decryption utilities
26
+ โ”‚ โ”œโ”€โ”€ dashboardService.js # Dashboard business logic
27
+ โ”‚ โ””โ”€โ”€ settingsService.js # Settings business logic
28
+ โ”œโ”€โ”€ middleware/ # Express middleware
29
+ โ”‚ โ””โ”€โ”€ authMiddleware.js # JWT authentication middleware
30
+ โ”œโ”€โ”€ .env # Environment variables
31
+ โ”œโ”€โ”€ package.json # Dependencies and scripts
32
+ โ””โ”€โ”€ server.js # Main application entry point
33
+ ```
34
+
35
+ ## ๐Ÿš€ Getting Started
36
+
37
+ ### Prerequisites
38
+
39
+ - Node.js >= 20
40
+ - npm or yarn
41
+ - MySQL, MariaDB, or PostgreSQL database server
42
+
43
+ ### Installation
44
+
45
+ Dependencies are automatically installed during project creation. To reinstall:
46
+
47
+ ```bash
48
+ npm install
49
+ ```
50
+
51
+ ### Environment Variables
52
+
53
+ Configure your environment variables in the `.env` file:
54
+
55
+ ```env
56
+ # Server Configuration
57
+ PORT=5000
58
+ CLIENT_URL=http://localhost:5173
59
+
60
+ # Security
61
+ JWT_SECRET=your_jwt_secret_key
62
+ PASSWORD_ENCRYPTION_KEY=your_encryption_key
63
+
64
+ # Database Configuration (if you added databases)
65
+ YOUR_DB_USER=username
66
+ YOUR_DB_PASSWORD=password
67
+ YOUR_DB_NAME=database_name
68
+ YOUR_DB_HOST=localhost
69
+ YOUR_DB_PORT=3306
70
+ ```
71
+
72
+ ### Running the Server
73
+
74
+ **Development mode** (with auto-reload):
75
+ ```bash
76
+ npm run dev
77
+ ```
78
+
79
+ **Production mode**:
80
+ ```bash
81
+ npm start
82
+ ```
83
+
84
+ The server will start on `http://localhost:5000` (or the PORT specified in .env).
85
+
86
+ ## ๐Ÿ—„๏ธ Working with Databases
87
+
88
+ ### Multiple Database Support
89
+
90
+ This backend supports connecting to multiple databases simultaneously. Each database has its own:
91
+ - Configuration file in `DB/`
92
+ - Models folder in `Models/[DB_NAME]/`
93
+ - Environment variables
94
+
95
+ ### Database Configuration
96
+
97
+ All databases are registered in `DB/dbConfigs.js`:
98
+
99
+ ```javascript
100
+ const dbConfigs = [
101
+ {
102
+ key: "MAIN_DB", // Identifier used in code
103
+ folder: "MAIN_DB", // Folder name in Models/
104
+ configPath: "/../DB/MAIN_DB.config.js" // Path to config file
105
+ },
106
+ // Add more databases here...
107
+ ];
108
+ ```
109
+
110
+ ### Adding a New Database
111
+
112
+ Use the CLI command:
113
+
114
+ ```bash
115
+ npx create-fullstack-app add-db
116
+ ```
117
+
118
+ This will:
119
+ 1. Prompt for database credentials
120
+ 2. Test the connection
121
+ 3. Create configuration files
122
+ 4. Generate a sample model
123
+ 5. Update environment variables
124
+
125
+ ### Importing and Using Databases
126
+
127
+ #### Import All Databases
128
+
129
+ ```javascript
130
+ const databases = require('./Models');
131
+ ```
132
+
133
+ The `databases` object contains all your database connections:
134
+
135
+ ```javascript
136
+ {
137
+ MAIN_DB: {
138
+ sequelize: [Sequelize Instance],
139
+ Sequelize: [Sequelize Class],
140
+ User: [User Model],
141
+ Product: [Product Model],
142
+ // ... other models
143
+ },
144
+ REPORTING_DB: {
145
+ sequelize: [Sequelize Instance],
146
+ Sequelize: [Sequelize Class],
147
+ Report: [Report Model],
148
+ // ... other models
149
+ }
150
+ }
151
+ ```
152
+
153
+ #### Import a Specific Database
154
+
155
+ ```javascript
156
+ const { MAIN_DB } = require('./Models');
157
+
158
+ // Access models
159
+ const { User, Product } = MAIN_DB;
160
+ ```
161
+
162
+ #### Import a Specific Model
163
+
164
+ ```javascript
165
+ const { MAIN_DB } = require('./Models');
166
+ const User = MAIN_DB.User;
167
+
168
+ // Or destructure directly
169
+ const { User, Product } = require('./Models').MAIN_DB;
170
+ ```
171
+
172
+ ### Using Sequelize Commands
173
+
174
+ #### Create a New Record
175
+
176
+ ```javascript
177
+ const { MAIN_DB } = require('./Models');
178
+ const { User } = MAIN_DB;
179
+
180
+ // Create
181
+ const newUser = await User.create({
182
+ username: 'john_doe',
183
+ email: 'john@example.com',
184
+ password: 'hashed_password'
185
+ });
186
+ ```
187
+
188
+ #### Find Records
189
+
190
+ ```javascript
191
+ // Find all
192
+ const allUsers = await User.findAll();
193
+
194
+ // Find with conditions
195
+ const activeUsers = await User.findAll({
196
+ where: { status: 'active' }
197
+ });
198
+
199
+ // Find one by primary key
200
+ const user = await User.findByPk(1);
201
+
202
+ // Find one with condition
203
+ const user = await User.findOne({
204
+ where: { email: 'john@example.com' }
205
+ });
206
+ ```
207
+
208
+ #### Update Records
209
+
210
+ ```javascript
211
+ // Update instance
212
+ const user = await User.findByPk(1);
213
+ await user.update({ username: 'new_username' });
214
+
215
+ // Bulk update
216
+ await User.update(
217
+ { status: 'inactive' },
218
+ { where: { lastLogin: { [Op.lt]: new Date('2023-01-01') } } }
219
+ );
220
+ ```
221
+
222
+ #### Delete Records
223
+
224
+ ```javascript
225
+ // Delete instance
226
+ const user = await User.findByPk(1);
227
+ await user.destroy();
228
+
229
+ // Bulk delete
230
+ await User.destroy({
231
+ where: { status: 'deleted' }
232
+ });
233
+ ```
234
+
235
+ #### Complex Queries
236
+
237
+ ```javascript
238
+ const { Op } = require('sequelize');
239
+
240
+ // Where operators
241
+ const users = await User.findAll({
242
+ where: {
243
+ age: { [Op.gte]: 18 },
244
+ status: { [Op.in]: ['active', 'pending'] },
245
+ email: { [Op.like]: '%@gmail.com' }
246
+ }
247
+ });
248
+
249
+ // Ordering
250
+ const sortedUsers = await User.findAll({
251
+ order: [['createdAt', 'DESC']]
252
+ });
253
+
254
+ // Limiting and pagination
255
+ const page = 1;
256
+ const limit = 10;
257
+ const offset = (page - 1) * limit;
258
+
259
+ const paginatedUsers = await User.findAndCountAll({
260
+ limit,
261
+ offset
262
+ });
263
+ ```
264
+
265
+ #### Associations
266
+
267
+ ```javascript
268
+ // Define associations in your model file
269
+ User.associate = function(models) {
270
+ User.hasMany(models.Post, { foreignKey: 'userId' });
271
+ User.belongsTo(models.Role, { foreignKey: 'roleId' });
272
+ };
273
+
274
+ // Query with associations
275
+ const userWithPosts = await User.findOne({
276
+ where: { id: 1 },
277
+ include: [{
278
+ model: Post,
279
+ as: 'posts'
280
+ }]
281
+ });
282
+ ```
283
+
284
+ #### Transactions
285
+
286
+ ```javascript
287
+ const { sequelize } = MAIN_DB;
288
+
289
+ const t = await sequelize.transaction();
290
+
291
+ try {
292
+ const user = await User.create({
293
+ username: 'john'
294
+ }, { transaction: t });
295
+
296
+ await Post.create({
297
+ userId: user.id,
298
+ title: 'First Post'
299
+ }, { transaction: t });
300
+
301
+ await t.commit();
302
+ } catch (error) {
303
+ await t.rollback();
304
+ throw error;
305
+ }
306
+ ```
307
+
308
+ ## ๐Ÿ›ฃ๏ธ Working with Routes
309
+
310
+ ### Adding a New Route
311
+
312
+ Use the CLI command:
313
+
314
+ ```bash
315
+ npx create-fullstack-app add-route
316
+ ```
317
+
318
+ This will:
319
+ 1. Prompt for route information
320
+ 2. Create a route file in `routes/`
321
+ 3. Create a service file in `services/`
322
+ 4. Update `routes/index.js` automatically
323
+
324
+ ### Route Structure
325
+
326
+ Routes should be thin and delegate logic to services:
327
+
328
+ ```javascript
329
+ // routes/usersRoutes.js
330
+ const express = require('express');
331
+ const router = express.Router();
332
+ const { authenticateToken } = require('../middleware/authMiddleware');
333
+ const usersService = require('../services/usersService');
334
+
335
+ router.get('/', authenticateToken, usersService.getAll);
336
+ router.get('/:id', authenticateToken, usersService.getById);
337
+ router.post('/', authenticateToken, usersService.create);
338
+ router.put('/:id', authenticateToken, usersService.update);
339
+ router.delete('/:id', authenticateToken, usersService.delete);
340
+
341
+ module.exports = router;
342
+ ```
343
+
344
+ ### Service Structure
345
+
346
+ Services contain business logic:
347
+
348
+ ```javascript
349
+ // services/usersService.js
350
+ const { MAIN_DB } = require('../Models');
351
+ const { User } = MAIN_DB;
352
+
353
+ exports.getAll = async (req, res) => {
354
+ try {
355
+ const users = await User.findAll();
356
+ res.json(users);
357
+ } catch (error) {
358
+ console.error('Error fetching users:', error);
359
+ res.status(500).json({ message: 'Error fetching users', error: error.message });
360
+ }
361
+ };
362
+
363
+ exports.getById = async (req, res) => {
364
+ try {
365
+ const { id } = req.params;
366
+ const user = await User.findByPk(id);
367
+
368
+ if (!user) {
369
+ return res.status(404).json({ message: 'User not found' });
370
+ }
371
+
372
+ res.json(user);
373
+ } catch (error) {
374
+ res.status(500).json({ message: 'Error fetching user', error: error.message });
375
+ }
376
+ };
377
+ ```
378
+
379
+ ## ๐Ÿ” Authentication
380
+
381
+ The backend includes JWT-based authentication:
382
+
383
+ ### Protecting Routes
384
+
385
+ ```javascript
386
+ const { authenticateToken } = require('../middleware/authMiddleware');
387
+
388
+ router.get('/protected', authenticateToken, (req, res) => {
389
+ // req.user contains the decoded JWT payload
390
+ res.json({ message: 'This is protected', user: req.user });
391
+ });
392
+ ```
393
+
394
+ ### Authentication Flow
395
+
396
+ 1. User logs in via `/api/auth/login`
397
+ 2. Server validates credentials and returns JWT token
398
+ 3. Client stores token and sends it in subsequent requests
399
+ 4. `authenticateToken` middleware verifies the token
400
+
401
+ ## ๐Ÿ“ Model Creation
402
+
403
+ ### Creating a New Model
404
+
405
+ Create a file in `Models/[DB_NAME]/modelName.js`:
406
+
407
+ ```javascript
408
+ 'use strict';
409
+ module.exports = (sequelize, DataTypes) => {
410
+ const User = sequelize.define('User', {
411
+ id: {
412
+ type: DataTypes.INTEGER,
413
+ primaryKey: true,
414
+ autoIncrement: true
415
+ },
416
+ username: {
417
+ type: DataTypes.STRING(50),
418
+ allowNull: false,
419
+ unique: true
420
+ },
421
+ email: {
422
+ type: DataTypes.STRING(100),
423
+ allowNull: false,
424
+ unique: true,
425
+ validate: {
426
+ isEmail: true
427
+ }
428
+ },
429
+ password: {
430
+ type: DataTypes.STRING(255),
431
+ allowNull: false
432
+ },
433
+ status: {
434
+ type: DataTypes.ENUM('active', 'inactive', 'suspended'),
435
+ defaultValue: 'active'
436
+ }
437
+ }, {
438
+ tableName: 'users',
439
+ timestamps: true // Adds createdAt and updatedAt
440
+ });
441
+
442
+ User.associate = function(models) {
443
+ // Define associations here
444
+ User.hasMany(models.Post, { foreignKey: 'userId', as: 'posts' });
445
+ };
446
+
447
+ return User;
448
+ };
449
+ ```
450
+
451
+ ### Data Types Reference
452
+
453
+ Common Sequelize data types:
454
+
455
+ - `DataTypes.STRING(length)` - VARCHAR
456
+ - `DataTypes.TEXT` - TEXT
457
+ - `DataTypes.INTEGER` - INTEGER
458
+ - `DataTypes.BIGINT` - BIGINT
459
+ - `DataTypes.FLOAT` - FLOAT
460
+ - `DataTypes.DOUBLE` - DOUBLE
461
+ - `DataTypes.DECIMAL(precision, scale)` - DECIMAL
462
+ - `DataTypes.BOOLEAN` - BOOLEAN
463
+ - `DataTypes.DATE` - DATETIME
464
+ - `DataTypes.DATEONLY` - DATE
465
+ - `DataTypes.JSON` - JSON
466
+ - `DataTypes.JSONB` - JSONB (PostgreSQL)
467
+ - `DataTypes.ENUM('value1', 'value2')` - ENUM
468
+ - `DataTypes.UUID` - UUID
469
+
470
+ ## ๐Ÿงช Testing
471
+
472
+ Add your test files and update package.json with test scripts:
473
+
474
+ ```bash
475
+ npm install --save-dev jest supertest
476
+ ```
477
+
478
+ ```javascript
479
+ // __tests__/users.test.js
480
+ const request = require('supertest');
481
+ const app = require('../server');
482
+
483
+ describe('User API', () => {
484
+ test('GET /api/users should return users', async () => {
485
+ const response = await request(app).get('/api/users');
486
+ expect(response.statusCode).toBe(200);
487
+ expect(Array.isArray(response.body)).toBe(true);
488
+ });
489
+ });
490
+ ```
491
+
492
+ ## ๐Ÿ“š Additional Resources
493
+
494
+ - [Express.js Documentation](https://expressjs.com/)
495
+ - [Sequelize Documentation](https://sequelize.org/)
496
+ - [Node.js Best Practices](https://github.com/goldbergyoni/nodebestpractices)
497
+
498
+ ## ๐Ÿค Contributing
499
+
500
+ When adding new features:
501
+
502
+ 1. Create models in appropriate database folders
503
+ 2. Create services for business logic
504
+ 3. Create routes for API endpoints
505
+ 4. Update this README if needed
506
+ 5. Test your changes thoroughly
507
+
508
+ ## ๐Ÿ› Troubleshooting
509
+
510
+ ### Database Connection Issues
511
+
512
+ - Verify credentials in `.env`
513
+ - Ensure database server is running
514
+ - Check network connectivity
515
+ - Review logs in the console
516
+
517
+ ### Module Not Found Errors
518
+
519
+ ```bash
520
+ npm install
521
+ ```
522
+
523
+ ### Port Already in Use
524
+
525
+ Change the PORT in `.env` or kill the process using the port:
526
+
527
+ ```bash
528
+ # Windows
529
+ netstat -ano | findstr :5000
530
+ taskkill /PID <PID> /F
531
+
532
+ # Linux/Mac
533
+ lsof -i :5000
534
+ kill -9 <PID>
535
+ ```
@@ -0,0 +1,19 @@
1
+ const jwt = require('jsonwebtoken');
2
+ const JWT_SECRET = process.env.JWT_SECRET;
3
+
4
+ exports.authenticateToken = (req, res, next) => {
5
+ const authHeader = req.headers['authorization'];
6
+ const token = authHeader && authHeader.split(' ')[1];
7
+
8
+ if (!token) {
9
+ return res.status(401).json({ message: 'Access token required' });
10
+ }
11
+
12
+ jwt.verify(token, JWT_SECRET, (err, user) => {
13
+ if (err) {
14
+ return res.status(403).json({ message: 'Invalid or expired token' });
15
+ }
16
+ req.user = user;
17
+ next();
18
+ });
19
+ };