alpe-temp 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 (56) hide show
  1. package/.env.example +13 -0
  2. package/backend-project/README.md +133 -0
  3. package/backend-project/package-lock.json +2559 -0
  4. package/backend-project/package.json +25 -0
  5. package/backend-project/server.js +28 -0
  6. package/backend-project/src/app.js +84 -0
  7. package/backend-project/src/config/app.config.js +72 -0
  8. package/backend-project/src/config/db.js +20 -0
  9. package/backend-project/src/config/env.js +19 -0
  10. package/backend-project/src/middleware/auth.middleware.js +33 -0
  11. package/backend-project/src/middleware/error.middleware.js +19 -0
  12. package/backend-project/src/modules/_example/example.controller.js +82 -0
  13. package/backend-project/src/modules/_example/example.model.js +47 -0
  14. package/backend-project/src/modules/_example/example.routes.js +43 -0
  15. package/backend-project/src/modules/_example/example.service.js +58 -0
  16. package/backend-project/src/modules/auth/auth.controller.js +47 -0
  17. package/backend-project/src/modules/auth/auth.routes.js +16 -0
  18. package/backend-project/src/modules/auth/auth.service.js +57 -0
  19. package/backend-project/src/modules/auth/user.model.js +41 -0
  20. package/backend-project/src/modules/department/department.controller.js +54 -0
  21. package/backend-project/src/modules/department/department.model.js +10 -0
  22. package/backend-project/src/modules/department/department.routes.js +15 -0
  23. package/backend-project/src/modules/department/department.service.js +29 -0
  24. package/backend-project/src/modules/employee/employee.controller.js +63 -0
  25. package/backend-project/src/modules/employee/employee.model.js +15 -0
  26. package/backend-project/src/modules/employee/employee.routes.js +16 -0
  27. package/backend-project/src/modules/employee/employee.service.js +30 -0
  28. package/backend-project/src/modules/excel/excel.controller.js +61 -0
  29. package/backend-project/src/modules/excel/excel.routes.js +13 -0
  30. package/backend-project/src/modules/excel/excel.service.js +303 -0
  31. package/backend-project/src/modules/reports/reports.controller.js +41 -0
  32. package/backend-project/src/modules/reports/reports.routes.js +10 -0
  33. package/backend-project/src/modules/salary/salary.controller.js +70 -0
  34. package/backend-project/src/modules/salary/salary.model.js +23 -0
  35. package/backend-project/src/modules/salary/salary.routes.js +16 -0
  36. package/backend-project/src/modules/salary/salary.service.js +44 -0
  37. package/backend-project/src/seed.js +36 -0
  38. package/backend-project/src/utils/response.js +35 -0
  39. package/backend-project/src/utils/token.js +27 -0
  40. package/bin/epms.js +161 -0
  41. package/frontend-project/README.md +16 -0
  42. package/frontend-project/dist/assets/index-B08ICGra.js +20 -0
  43. package/frontend-project/dist/assets/index-D_cqT2Z6.css +1 -0
  44. package/frontend-project/dist/car.jfif +0 -0
  45. package/frontend-project/dist/favicon.svg +1 -0
  46. package/frontend-project/dist/icons.svg +24 -0
  47. package/frontend-project/dist/index.html +14 -0
  48. package/frontend-project/dist/logo.png +0 -0
  49. package/frontend-project/eslint.config.js +21 -0
  50. package/frontend-project/index.html +13 -0
  51. package/frontend-project/package-lock.json +3660 -0
  52. package/frontend-project/package.json +33 -0
  53. package/frontend-project/postcss.config.js +6 -0
  54. package/frontend-project/tailwind.config.js +15 -0
  55. package/frontend-project/vite.config.js +8 -0
  56. package/package.json +41 -0
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "modular-auth-backend",
3
+ "version": "1.0.0",
4
+ "description": "Modular Node.js backend with auth and Excel export utility",
5
+ "main": "server.js",
6
+ "scripts": {
7
+ "start": "node server.js",
8
+ "dev": "nodemon server.js",
9
+ "seed": "node src/seed.js"
10
+ },
11
+ "dependencies": {
12
+ "bcryptjs": "^2.4.3",
13
+ "cors": "^2.8.5",
14
+ "dotenv": "^16.4.5",
15
+ "exceljs": "^4.4.0",
16
+ "express": "^4.19.2",
17
+ "mongoose": "^8.5.0",
18
+ "helmet": "^7.1.0",
19
+ "jsonwebtoken": "^9.0.2",
20
+ "uuid": "^10.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "nodemon": "^3.1.4"
24
+ }
25
+ }
@@ -0,0 +1,28 @@
1
+ const app = require('./src/app');
2
+ const env = require('./src/config/env');
3
+
4
+ const start = async () => {
5
+ await app.connectDB();
6
+
7
+ const server = app.listen(env.PORT, () => {
8
+ console.log(`\n Server running on http://localhost:${env.PORT}`);
9
+ console.log(` Environment : ${env.NODE_ENV}`);
10
+ console.log(` Health : http://localhost:${env.PORT}/health\n`);
11
+ });
12
+
13
+ const shutdown = (signal) => {
14
+ console.log(`\n${signal} received — shutting down gracefully...`);
15
+ server.close(() => {
16
+ console.log('Server closed.');
17
+ process.exit(0);
18
+ });
19
+ };
20
+
21
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
22
+ process.on('SIGINT', () => shutdown('SIGINT'));
23
+ };
24
+
25
+ start().catch((err) => {
26
+ console.error('Failed to start server:', err.message);
27
+ process.exit(1);
28
+ });
@@ -0,0 +1,84 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // 🚀 APP — Express application setup
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // - Creates the Express app
7
+ // - Adds middleware (security, CORS, JSON parsing)
8
+ // - Registers all API module routes
9
+ // - Exports the app for server.js to use
10
+ //
11
+ // HOW TO ADD A NEW MODULE:
12
+ // 1. Add its routes to src/config/app.config.js (registeredRoutes array)
13
+ // 2. Add a use() line below (see the PATTERN section)
14
+ // 3. Done! Your new API is live.
15
+ //
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+
18
+ const express = require('express');
19
+ const path = require('path');
20
+ const helmet = require('helmet');
21
+ const cors = require('cors');
22
+ const db = require('./config/db');
23
+ const cfg = require('./config/app.config');
24
+
25
+ const { errorHandler, notFoundHandler } = require('./middleware/error.middleware');
26
+
27
+ const app = express();
28
+
29
+ // ─── GLOBAL MIDDLEWARE (applied to every request) ────────────────────────────
30
+ app.use(helmet()); // security headers
31
+ app.use(cors()); // allow cross-origin requests
32
+ app.use(express.json({ limit: '10mb' })); // parse JSON bodies
33
+ app.use(express.urlencoded({ extended: true }));
34
+
35
+ // ─── HEALTH CHECK ────────────────────────────────────────────────────────────
36
+ // Every scenario needs a health endpoint for deployment monitoring.
37
+ app.get('/health', (_req, res) =>
38
+ res.json({
39
+ status: 'ok',
40
+ timestamp: new Date().toISOString(),
41
+ modules: cfg.registeredRoutes.map((m) => m.name),
42
+ })
43
+ );
44
+
45
+ // ╔═══════════════════════════════════════════════════════════════════════════╗
46
+ // ║ 📌 PATTERN: Register a new module ║
47
+ // ║ ║
48
+ // ║ Step 1. In app.config.js, add to registeredRoutes: ║
49
+ // ║ { name: 'products', routes: require('./modules/product/product.routes') } ║
50
+ // ║ ║
51
+ // ║ Step 2. Add one line below: ║
52
+ // ║ app.use('/api/products', require('./modules/product/product.routes')); ║
53
+ // ╚═══════════════════════════════════════════════════════════════════════════╝
54
+
55
+ // ─── MODULE ROUTES ───────────────────────────────────────────────────────────
56
+ // Each line starts a new API group under /api/...
57
+ // The route file inside each module handles its own sub-routes.
58
+ //
59
+ app.use('/api/auth', require('./modules/auth/auth.routes'));
60
+ app.use('/api/excel', require('./modules/excel/excel.routes'));
61
+ app.use('/api/employees', require('./modules/employee/employee.routes'));
62
+ app.use('/api/departments', require('./modules/department/department.routes'));
63
+ app.use('/api/salaries', require('./modules/salary/salary.routes'));
64
+ app.use('/api/reports', require('./modules/reports/reports.routes'));
65
+
66
+ // ─── FRONTEND SPA (serves built React app) ────────────────────────────────────
67
+ const distPath = path.join(__dirname, '..', '..', 'frontend-project', 'dist');
68
+ app.use(express.static(distPath));
69
+
70
+ app.get('*', (req, res, next) => {
71
+ if (req.path.startsWith('/api')) return next();
72
+ res.sendFile(path.join(distPath, 'index.html'));
73
+ });
74
+
75
+ // ─── ERROR HANDLING (must be last) ───────────────────────────────────────────
76
+ // These catch any errors from routes above.
77
+ app.use(notFoundHandler); // handles 404 - route not found
78
+ app.use(errorHandler); // handles 500 - server errors
79
+
80
+ // ─── DATABASE CONNECTION ─────────────────────────────────────────────────────
81
+ // Called by server.js (not here) so the app is testable without a DB.
82
+ app.connectDB = () => db.connect();
83
+
84
+ module.exports = app;
@@ -0,0 +1,72 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // ⚙️ APP CONFIG — One place to control the whole backend
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // - Loads environment variables from .env (via env.js)
7
+ // - Lists every registered module (so you can add/remove features)
8
+ // - Exports everything in one easy-to-find object
9
+ //
10
+ // HOW TO ADD A NEW FEATURE (e.g. "Products"):
11
+ // 1. Create folder: src/modules/product/
12
+ // 2. Copy files from src/modules/_example/ (rename to product.*)
13
+ // 3. Import routes below in this file (see REGISTERED MODULES)
14
+ // 4. Add route line in app.js (see instructions there)
15
+ //
16
+ // ═══════════════════════════════════════════════════════════════════════════
17
+
18
+ const env = require('./env');
19
+
20
+ // ─── SERVER SETTINGS ─────────────────────────────────────────────────────────
21
+ const server = {
22
+ PORT: env.PORT,
23
+ NODE_ENV: env.NODE_ENV,
24
+ };
25
+
26
+ // ─── DATABASE ────────────────────────────────────────────────────────────────
27
+ const database = {
28
+ URI: env.MONGODB_URI,
29
+ };
30
+
31
+ // ─── JWT AUTHENTICATION ──────────────────────────────────────────────────────
32
+ const jwt = {
33
+ SECRET: env.JWT_SECRET,
34
+ EXPIRES_IN: env.JWT_EXPIRES_IN,
35
+ REFRESH_SECRET: env.JWT_REFRESH_SECRET,
36
+ REFRESH_EXPIRES_IN: env.JWT_REFRESH_EXPIRES_IN,
37
+ };
38
+
39
+ // ─── BCRYPT ──────────────────────────────────────────────────────────────────
40
+ const bcrypt = {
41
+ ROUNDS: env.BCRYPT_ROUNDS,
42
+ };
43
+
44
+ // ─── REGISTERED MODULES ──────────────────────────────────────────────────────
45
+ // 🔵 To ADD a new module:
46
+ // 1. Import its routes: const productRoutes = require('../modules/product/product.routes');
47
+ // 2. Add to the list: { name: 'products', routes: productRoutes }
48
+ //
49
+ // 🔴 To REMOVE a module:
50
+ // Just delete its line from this array (and the import above).
51
+ //
52
+ // Every module in this list automatically gets:
53
+ // - Route registration in app.js
54
+ // - Listed in the /health endpoint for debugging
55
+ //
56
+ const registeredRoutes = [
57
+ { name: 'auth', routes: require('../modules/auth/auth.routes') },
58
+ { name: 'employees', routes: require('../modules/employee/employee.routes') },
59
+ { name: 'departments', routes: require('../modules/department/department.routes') },
60
+ { name: 'salaries', routes: require('../modules/salary/salary.routes') },
61
+ { name: 'reports', routes: require('../modules/reports/reports.routes') },
62
+ { name: 'excel', routes: require('../modules/excel/excel.routes') },
63
+ ];
64
+
65
+ // ─── EXPORT EVERYTHING ───────────────────────────────────────────────────────
66
+ module.exports = {
67
+ server,
68
+ database,
69
+ jwt,
70
+ bcrypt,
71
+ registeredRoutes,
72
+ };
@@ -0,0 +1,20 @@
1
+ const mongoose = require('mongoose');
2
+ const env = require('./env');
3
+
4
+ const connect = async () => {
5
+ mongoose.connection.on('connected', () =>
6
+ console.log(`MongoDB connected → ${mongoose.connection.host}`)
7
+ );
8
+ mongoose.connection.on('error', (err) =>
9
+ console.error('MongoDB error:', err.message)
10
+ );
11
+ mongoose.connection.on('disconnected', () =>
12
+ console.warn('MongoDB disconnected')
13
+ );
14
+
15
+ await mongoose.connect(env.MONGODB_URI);
16
+ };
17
+
18
+ const disconnect = async () => mongoose.disconnect();
19
+
20
+ module.exports = { connect, disconnect };
@@ -0,0 +1,19 @@
1
+ require('dotenv').config();
2
+
3
+ const env = {
4
+ PORT: process.env.PORT || 3000,
5
+ NODE_ENV: process.env.NODE_ENV || 'development',
6
+
7
+ MONGODB_URI: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/auth_db',
8
+
9
+ JWT_SECRET: process.env.JWT_SECRET || 'change-this-secret-in-production',
10
+ JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '7d',
11
+ JWT_REFRESH_SECRET: process.env.JWT_REFRESH_SECRET || 'change-this-refresh-secret',
12
+ JWT_REFRESH_EXPIRES_IN: process.env.JWT_REFRESH_EXPIRES_IN || '30d',
13
+
14
+ BCRYPT_ROUNDS: parseInt(process.env.BCRYPT_ROUNDS || '12', 10),
15
+
16
+ EXCEL_OUTPUT_DIR: process.env.EXCEL_OUTPUT_DIR || './exports',
17
+ };
18
+
19
+ module.exports = env;
@@ -0,0 +1,33 @@
1
+ const { verifyAccessToken } = require('../utils/token');
2
+ const res_ = require('../utils/response');
3
+
4
+ /**
5
+ * authenticate — verifies the Bearer token and attaches `req.user`.
6
+ */
7
+ const authenticate = (req, res, next) => {
8
+ const header = req.headers.authorization || '';
9
+ const token = header.startsWith('Bearer ') ? header.slice(7) : null;
10
+
11
+ if (!token) return res_.unauthorized(res, 'No token provided');
12
+
13
+ try {
14
+ req.user = verifyAccessToken(token);
15
+ return next();
16
+ } catch (err) {
17
+ const message = err.name === 'TokenExpiredError' ? 'Token expired' : 'Invalid token';
18
+ return res_.unauthorized(res, message);
19
+ }
20
+ };
21
+
22
+ /**
23
+ * authorize — gates a route to specific roles.
24
+ * Usage: router.delete('/admin', authenticate, authorize('admin'), handler)
25
+ */
26
+ const authorize = (...roles) => (req, res, next) => {
27
+ if (!roles.includes(req.user?.role)) {
28
+ return res_.forbidden(res, 'Insufficient permissions');
29
+ }
30
+ return next();
31
+ };
32
+
33
+ module.exports = { authenticate, authorize };
@@ -0,0 +1,19 @@
1
+ const env = require('../config/env');
2
+ const res_ = require('../utils/response');
3
+
4
+ // eslint-disable-next-line no-unused-vars
5
+ const errorHandler = (err, req, res, _next) => {
6
+ const statusCode = err.statusCode || 500;
7
+ const message = err.message || 'Internal server error';
8
+
9
+ if (env.NODE_ENV !== 'production') {
10
+ console.error(`[${req.method}] ${req.originalUrl} →`, err);
11
+ }
12
+
13
+ return res_.error(res, message, statusCode);
14
+ };
15
+
16
+ const notFoundHandler = (req, res) =>
17
+ res_.notFound(res, `Route ${req.method} ${req.originalUrl} not found`);
18
+
19
+ module.exports = { errorHandler, notFoundHandler };
@@ -0,0 +1,82 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // 📦 EXAMPLE CONTROLLER — Handles HTTP requests and sends responses
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // - Receives incoming HTTP requests (from routes)
7
+ // - Calls the service to do the actual work
8
+ // - Sends back a JSON response to the client
9
+ //
10
+ // HOW IT WORKS:
11
+ // 1. The route calls a controller function (e.g. create)
12
+ // 2. The controller reads the request data (req.body, req.params)
13
+ // 3. It calls the service to handle the database operation
14
+ // 4. It sends back a success or error response
15
+ //
16
+ // RESPONSE HELPERS (from utils/response.js):
17
+ // res_.success(res, data, message) → 200 OK
18
+ // res_.created(res, data, message) → 201 Created
19
+ // res_.error(res, message, statusCode) → any error
20
+ // res_.notFound(res, message) → 404
21
+ //
22
+ // ═══════════════════════════════════════════════════════════════════════════
23
+
24
+ const ExampleService = require('./example.service');
25
+ const res_ = require('../../utils/response');
26
+
27
+ const ExampleController = {
28
+ // ─── POST /api/examples (add new) ────────────────────────────────────
29
+ async create(req, res) {
30
+ try {
31
+ const record = await ExampleService.create(req.body);
32
+ return res_.created(res, record, 'Record created');
33
+ } catch (err) {
34
+ return res_.error(res, err.message, err.statusCode || 500);
35
+ }
36
+ },
37
+
38
+ // ─── GET /api/examples (list all) ────────────────────────────────────
39
+ async list(req, res) {
40
+ try {
41
+ const records = await ExampleService.list();
42
+ return res_.success(res, { records });
43
+ } catch (err) {
44
+ return res_.error(res, err.message, 500);
45
+ }
46
+ },
47
+
48
+ // ─── GET /api/examples/:id (get one) ─────────────────────────────────
49
+ async getById(req, res) {
50
+ try {
51
+ const record = await ExampleService.getById(req.params.id);
52
+ if (!record) return res_.notFound(res, 'Record not found');
53
+ return res_.success(res, record);
54
+ } catch (err) {
55
+ return res_.error(res, err.message, 500);
56
+ }
57
+ },
58
+
59
+ // ─── PUT /api/examples/:id (update) ──────────────────────────────────
60
+ async update(req, res) {
61
+ try {
62
+ const record = await ExampleService.update(req.params.id, req.body);
63
+ if (!record) return res_.notFound(res, 'Record not found');
64
+ return res_.success(res, record, 'Record updated');
65
+ } catch (err) {
66
+ return res_.error(res, err.message, 500);
67
+ }
68
+ },
69
+
70
+ // ─── DELETE /api/examples/:id (delete) ───────────────────────────────
71
+ async remove(req, res) {
72
+ try {
73
+ const record = await ExampleService.remove(req.params.id);
74
+ if (!record) return res_.notFound(res, 'Record not found');
75
+ return res_.success(res, null, 'Record deleted');
76
+ } catch (err) {
77
+ return res_.error(res, err.message, 500);
78
+ }
79
+ },
80
+ };
81
+
82
+ module.exports = ExampleController;
@@ -0,0 +1,47 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // 📦 EXAMPLE MODEL — Mongoose schema (database structure)
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // Defines the shape of your data in MongoDB.
7
+ // Each field = a column in the database.
8
+ //
9
+ // HOW TO USE:
10
+ // 1. Rename "Example" to your feature name (e.g. "Product")
11
+ // 2. Change the fields below to match your data
12
+ // 3. That's it! The model is ready to use in your service.
13
+ //
14
+ // EXAMPLE FIELDS (replace these):
15
+ // name: { type: String, required: true } ← text field
16
+ // price: { type: Number, default: 0 } ← number field
17
+ // category: { type: String, enum: ['a','b'] } ← dropdown/choice
18
+ // isActive: { type: Boolean, default: true } ← yes/no
19
+ // createdAt: added automatically by timestamps ← date
20
+ //
21
+ // ═══════════════════════════════════════════════════════════════════════════
22
+
23
+ const mongoose = require('mongoose');
24
+
25
+ const exampleSchema = new mongoose.Schema(
26
+ {
27
+ // ── YOUR FIELDS HERE ────────────────────────────────────────────────
28
+ name: {
29
+ type: String,
30
+ required: true,
31
+ trim: true,
32
+ },
33
+ description: {
34
+ type: String,
35
+ trim: true,
36
+ },
37
+ status: {
38
+ type: String,
39
+ enum: ['active', 'inactive'],
40
+ default: 'active',
41
+ },
42
+ // Add more fields as needed
43
+ },
44
+ { timestamps: true } // adds createdAt and updatedAt automatically
45
+ );
46
+
47
+ module.exports = mongoose.model('Example', exampleSchema);
@@ -0,0 +1,43 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // 📦 EXAMPLE ROUTES — Maps URLs to controller functions
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // - Connects a URL path to a controller function
7
+ // - Example: GET /api/examples → ExampleController.list
8
+ //
9
+ // HOW TO ADD A NEW ROUTE:
10
+ // router.get('/search', ExampleController.search) ← GET request
11
+ // router.post('/', ExampleController.create) ← POST request
12
+ // router.put('/:id', ExampleController.update) ← PUT request
13
+ // router.delete('/:id', ExampleController.remove) ← DELETE request
14
+ //
15
+ // COMMON HTTP METHODS:
16
+ // GET → fetch data
17
+ // POST → create new data
18
+ // PUT → update existing data
19
+ // DELETE → remove data
20
+ //
21
+ // AUTHENTICATION:
22
+ // - Add `authenticate` before any route to require login
23
+ // - Example: router.get('/', authenticate, ExampleController.list)
24
+ //
25
+ // ═══════════════════════════════════════════════════════════════════════════
26
+
27
+ const { Router } = require('express');
28
+ const ExampleController = require('./example.controller');
29
+ const { authenticate } = require('../../middleware/auth.middleware');
30
+
31
+ const router = Router();
32
+
33
+ // ─── All routes require authentication ─────────────────────────────────────
34
+ router.use(authenticate);
35
+
36
+ // ─── CRUD ROUTES ────────────────────────────────────────────────────────────
37
+ router.post('/', ExampleController.create); // POST /api/examples
38
+ router.get('/', ExampleController.list); // GET /api/examples
39
+ router.get('/:id', ExampleController.getById); // GET /api/examples/:id
40
+ router.put('/:id', ExampleController.update); // PUT /api/examples/:id
41
+ router.delete('/:id', ExampleController.remove); // DELETE /api/examples/:id
42
+
43
+ module.exports = router;
@@ -0,0 +1,58 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════
2
+ // 📦 EXAMPLE SERVICE — Business logic (talks to database)
3
+ // ═══════════════════════════════════════════════════════════════════════════
4
+ //
5
+ // WHAT THIS FILE DOES:
6
+ // - Every function here does one job (create, list, get, update, delete)
7
+ // - The controller calls these functions
8
+ // - The model is used here to query MongoDB
9
+ //
10
+ // HOW TO ADD A NEW FUNCTION:
11
+ // Just add a new method to the object below.
12
+ // Example: async search(query) { ... }
13
+ //
14
+ // AVAILABLE FUNCTIONS (customize these):
15
+ // create(data) → adds a new record
16
+ // list() → gets all records
17
+ // getById(id) → gets one record by ID
18
+ // update(id, data) → updates a record
19
+ // remove(id) → deletes a record
20
+ //
21
+ // ═══════════════════════════════════════════════════════════════════════════
22
+
23
+ const Example = require('./example.model');
24
+
25
+ const ExampleService = {
26
+ // ─── CREATE ───────────────────────────────────────────────────────────
27
+ async create(data) {
28
+ const record = await Example.create(data);
29
+ return record;
30
+ },
31
+
32
+ // ─── LIST ALL ─────────────────────────────────────────────────────────
33
+ async list() {
34
+ return Example.find().sort({ createdAt: -1 });
35
+ },
36
+
37
+ // ─── GET ONE ──────────────────────────────────────────────────────────
38
+ async getById(id) {
39
+ return Example.findById(id);
40
+ },
41
+
42
+ // ─── UPDATE ───────────────────────────────────────────────────────────
43
+ async update(id, data) {
44
+ return Example.findByIdAndUpdate(id, data, { new: true });
45
+ },
46
+
47
+ // ─── DELETE ───────────────────────────────────────────────────────────
48
+ async remove(id) {
49
+ return Example.findByIdAndDelete(id);
50
+ },
51
+
52
+ // ─── COUNT ────────────────────────────────────────────────────────────
53
+ async count() {
54
+ return Example.countDocuments();
55
+ },
56
+ };
57
+
58
+ module.exports = ExampleService;
@@ -0,0 +1,47 @@
1
+ const AuthService = require('./auth.service');
2
+ const res_ = require('../../utils/response');
3
+
4
+ const AuthController = {
5
+ async signup(req, res) {
6
+ try {
7
+ const result = await AuthService.signup(req.body);
8
+ return res_.created(res, result, 'Account created successfully');
9
+ } catch (err) {
10
+ return res_.error(res, err.message, err.statusCode || 500);
11
+ }
12
+ },
13
+
14
+ async login(req, res) {
15
+ try {
16
+ const result = await AuthService.login(req.body);
17
+ return res_.success(res, result, 'Login successful');
18
+ } catch (err) {
19
+ return res_.error(res, err.message, err.statusCode || 500);
20
+ }
21
+ },
22
+
23
+ async refresh(req, res) {
24
+ try {
25
+ const result = await AuthService.refresh(req.body.refreshToken);
26
+ return res_.success(res, result, 'Tokens refreshed');
27
+ } catch (err) {
28
+ return res_.error(res, err.message, err.statusCode || 500);
29
+ }
30
+ },
31
+
32
+ async me(req, res) {
33
+ try {
34
+ const user = await AuthService.me(req.user.id);
35
+ return res_.success(res, user);
36
+ } catch (err) {
37
+ return res_.error(res, err.message, err.statusCode || 500);
38
+ }
39
+ },
40
+
41
+ logout(_req, res) {
42
+ // JWT logout is client-side. Add a token blocklist here for server-side invalidation.
43
+ return res_.success(res, null, 'Logged out successfully');
44
+ },
45
+ };
46
+
47
+ module.exports = AuthController;
@@ -0,0 +1,16 @@
1
+ const { Router } = require('express');
2
+ const AuthController = require('./auth.controller');
3
+ const { authenticate } = require('../../middleware/auth.middleware');
4
+
5
+ const router = Router();
6
+
7
+ // Public routes
8
+ router.post('/signup', AuthController.signup);
9
+ router.post('/login', AuthController.login);
10
+ router.post('/refresh', AuthController.refresh);
11
+
12
+ // Protected routes
13
+ router.get('/me', authenticate, AuthController.me);
14
+ router.post('/logout', authenticate, AuthController.logout);
15
+
16
+ module.exports = router;