@organizasyon/meeting-nanaman-app-backend 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 (101) hide show
  1. package/dist/controllers/auth/index.d.ts +65 -0
  2. package/dist/controllers/auth/index.js +525 -0
  3. package/dist/controllers/employees/index.d.ts +38 -0
  4. package/dist/controllers/employees/index.js +185 -0
  5. package/dist/controllers/health/index.d.ts +9 -0
  6. package/dist/controllers/health/index.js +42 -0
  7. package/dist/controllers/index.d.ts +16 -0
  8. package/dist/controllers/index.js +19 -0
  9. package/dist/controllers/meetings/index.d.ts +23 -0
  10. package/dist/controllers/meetings/index.js +233 -0
  11. package/dist/controllers/modules/index.d.ts +5 -0
  12. package/dist/controllers/modules/index.js +104 -0
  13. package/dist/controllers/users/index.d.ts +103 -0
  14. package/dist/controllers/users/index.js +841 -0
  15. package/dist/data/modules.json +94 -0
  16. package/dist/database/config/index.d.ts +2 -0
  17. package/dist/database/config/index.js +32 -0
  18. package/dist/database/index.d.ts +9 -0
  19. package/dist/database/index.js +9 -0
  20. package/dist/database/seeder/employees/index.d.ts +1 -0
  21. package/dist/database/seeder/employees/index.js +40 -0
  22. package/dist/database/seeder/index.d.ts +4 -0
  23. package/dist/database/seeder/index.js +20 -0
  24. package/dist/database/seeder/users/index.d.ts +1 -0
  25. package/dist/database/seeder/users/index.js +46 -0
  26. package/dist/index.d.ts +9 -0
  27. package/dist/index.js +23 -0
  28. package/dist/jobs/index.d.ts +1 -0
  29. package/dist/jobs/index.js +18 -0
  30. package/dist/jobs/mailer/index.d.ts +4 -0
  31. package/dist/jobs/mailer/index.js +186 -0
  32. package/dist/jobs/mailer/templates/auth.d.ts +11 -0
  33. package/dist/jobs/mailer/templates/auth.js +117 -0
  34. package/dist/jobs/mailer/templates/index.d.ts +1 -0
  35. package/dist/jobs/mailer/templates/index.js +17 -0
  36. package/dist/jobs/queues/index.d.ts +3 -0
  37. package/dist/jobs/queues/index.js +115 -0
  38. package/dist/middlewares/audit/index.d.ts +0 -0
  39. package/dist/middlewares/audit/index.js +1 -0
  40. package/dist/middlewares/guard/index.d.ts +11 -0
  41. package/dist/middlewares/guard/index.js +53 -0
  42. package/dist/middlewares/index.d.ts +2 -0
  43. package/dist/middlewares/index.js +7 -0
  44. package/dist/middlewares/meeting.d.ts +9 -0
  45. package/dist/middlewares/meeting.js +34 -0
  46. package/dist/models/employees/index.d.ts +83 -0
  47. package/dist/models/employees/index.js +70 -0
  48. package/dist/models/index.d.ts +570 -0
  49. package/dist/models/index.js +17 -0
  50. package/dist/models/meetings/index.d.ts +227 -0
  51. package/dist/models/meetings/index.js +112 -0
  52. package/dist/models/passkeys/index.d.ts +77 -0
  53. package/dist/models/passkeys/index.js +55 -0
  54. package/dist/models/queues/index.d.ts +77 -0
  55. package/dist/models/queues/index.js +57 -0
  56. package/dist/models/users/index.d.ts +107 -0
  57. package/dist/models/users/index.js +92 -0
  58. package/dist/queues/index.d.ts +1 -0
  59. package/dist/queues/index.js +17 -0
  60. package/dist/queues/mailer/index.d.ts +4 -0
  61. package/dist/queues/mailer/index.js +74 -0
  62. package/dist/types/index.d.ts +33 -0
  63. package/dist/types/index.js +2 -0
  64. package/dist/utils/notifications.d.ts +2 -0
  65. package/dist/utils/notifications.js +51 -0
  66. package/package.json +39 -0
  67. package/public/health.html +215 -0
  68. package/src/controllers/auth/index.ts +609 -0
  69. package/src/controllers/employees/index.ts +210 -0
  70. package/src/controllers/health/index.ts +41 -0
  71. package/src/controllers/index.ts +9 -0
  72. package/src/controllers/meetings/index.ts +251 -0
  73. package/src/controllers/modules/index.ts +74 -0
  74. package/src/controllers/users/index.ts +981 -0
  75. package/src/data/modules.json +94 -0
  76. package/src/database/config/index.ts +26 -0
  77. package/src/database/index.ts +5 -0
  78. package/src/database/seeder/employees/index.ts +35 -0
  79. package/src/database/seeder/index.ts +18 -0
  80. package/src/database/seeder/users/index.ts +44 -0
  81. package/src/index.ts +10 -0
  82. package/src/jobs/index.ts +2 -0
  83. package/src/jobs/mailer/index.ts +154 -0
  84. package/src/jobs/mailer/templates/auth.ts +113 -0
  85. package/src/jobs/mailer/templates/index.ts +1 -0
  86. package/src/jobs/queues/index.ts +125 -0
  87. package/src/middlewares/audit/index.ts +0 -0
  88. package/src/middlewares/guard/index.ts +64 -0
  89. package/src/middlewares/index.ts +5 -0
  90. package/src/middlewares/meeting.ts +45 -0
  91. package/src/models/employees/index.ts +70 -0
  92. package/src/models/index.ts +8 -0
  93. package/src/models/meetings/index.ts +112 -0
  94. package/src/models/passkeys/index.ts +53 -0
  95. package/src/models/queues/index.ts +55 -0
  96. package/src/models/users/index.ts +92 -0
  97. package/src/queues/index.ts +1 -0
  98. package/src/queues/mailer/index.ts +80 -0
  99. package/src/types/index.ts +38 -0
  100. package/src/utils/notifications.ts +66 -0
  101. package/tsconfig.json +18 -0
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const employees_1 = __importDefault(require("../../models/employees"));
7
+ class Employees {
8
+ /**
9
+ * Create a new employee
10
+ * Accepts form data with:
11
+ * - first_name (required)
12
+ * - middle_name (optional)
13
+ * - last_name (required)
14
+ * - address (optional)
15
+ * - contact_number (optional)
16
+ * - email (optional)
17
+ * - position (optional)
18
+ * - department (optional)
19
+ */
20
+ async create(req, res) {
21
+ try {
22
+ const body = req.body || {};
23
+ const firstName = (body.first_name ?? '').toString().trim();
24
+ const lastName = (body.last_name ?? '').toString().trim();
25
+ if (!firstName || !lastName) {
26
+ res.status(400).json({ message: 'first_name and last_name are required' });
27
+ return;
28
+ }
29
+ // Create employee record
30
+ const employee = await employees_1.default.create({
31
+ first_name: firstName,
32
+ middle_name: (body.middle_name ?? null),
33
+ last_name: lastName,
34
+ address: (body.address ?? null),
35
+ contact_number: (body.contact_number ?? null),
36
+ email: (body.email ?? null),
37
+ position: (body.position ?? null),
38
+ department: (body.department ?? null),
39
+ created_at: Date.now(),
40
+ updated_at: Date.now()
41
+ });
42
+ res.status(201).json({
43
+ message: 'Employee created successfully',
44
+ employee: {
45
+ id: employee._id,
46
+ first_name: employee.first_name,
47
+ middle_name: employee.middle_name,
48
+ last_name: employee.last_name,
49
+ email: employee.email,
50
+ position: employee.position,
51
+ department: employee.department,
52
+ contact_number: employee.contact_number,
53
+ address: employee.address
54
+ }
55
+ });
56
+ }
57
+ catch (err) {
58
+ console.error('Create employee error', err);
59
+ res.status(500).json({ message: 'Failed to create employee', error: String(err) });
60
+ }
61
+ }
62
+ /**
63
+ * Get all employees
64
+ */
65
+ async getAll(req, res) {
66
+ try {
67
+ const employees = await employees_1.default.find({ deleted_at: null })
68
+ .select('-__v')
69
+ .sort({ created_at: -1 })
70
+ .lean()
71
+ .exec();
72
+ res.json({
73
+ message: 'Employees retrieved successfully',
74
+ count: employees.length,
75
+ employees
76
+ });
77
+ }
78
+ catch (err) {
79
+ console.error('Get employees error', err);
80
+ res.status(500).json({ message: 'Failed to retrieve employees', error: String(err) });
81
+ }
82
+ }
83
+ /**
84
+ * Get employee by ID
85
+ */
86
+ async getById(req, res) {
87
+ try {
88
+ const { id } = req.params;
89
+ if (!id) {
90
+ res.status(400).json({ message: 'Employee ID is required' });
91
+ return;
92
+ }
93
+ const employee = await employees_1.default.findOne({
94
+ _id: id,
95
+ deleted_at: null
96
+ })
97
+ .select('-__v')
98
+ .lean()
99
+ .exec();
100
+ if (!employee) {
101
+ res.status(404).json({ message: 'Employee not found' });
102
+ return;
103
+ }
104
+ res.json({
105
+ message: 'Employee retrieved successfully',
106
+ employee
107
+ });
108
+ }
109
+ catch (err) {
110
+ console.error('Get employee error', err);
111
+ res.status(500).json({ message: 'Failed to retrieve employee', error: String(err) });
112
+ }
113
+ }
114
+ /**
115
+ * Update employee
116
+ */
117
+ async update(req, res) {
118
+ try {
119
+ const { id } = req.params;
120
+ const body = req.body || {};
121
+ if (!id) {
122
+ res.status(400).json({ message: 'Employee ID is required' });
123
+ return;
124
+ }
125
+ const updateData = {
126
+ updated_at: Date.now()
127
+ };
128
+ // Only update provided fields
129
+ const allowedFields = ['first_name', 'middle_name', 'last_name', 'address', 'contact_number', 'email', 'position', 'department'];
130
+ for (const field of allowedFields) {
131
+ if (body[field] !== undefined) {
132
+ updateData[field] = body[field];
133
+ }
134
+ }
135
+ const employee = await employees_1.default.findOneAndUpdate({ _id: id, deleted_at: null }, updateData, { new: true, runValidators: true })
136
+ .select('-__v')
137
+ .lean()
138
+ .exec();
139
+ if (!employee) {
140
+ res.status(404).json({ message: 'Employee not found' });
141
+ return;
142
+ }
143
+ res.json({
144
+ message: 'Employee updated successfully',
145
+ employee
146
+ });
147
+ }
148
+ catch (err) {
149
+ console.error('Update employee error', err);
150
+ res.status(500).json({ message: 'Failed to update employee', error: String(err) });
151
+ }
152
+ }
153
+ /**
154
+ * Soft delete employee
155
+ */
156
+ async delete(req, res) {
157
+ try {
158
+ const { id } = req.params;
159
+ if (!id) {
160
+ res.status(400).json({ message: 'Employee ID is required' });
161
+ return;
162
+ }
163
+ const employee = await employees_1.default.findOneAndUpdate({ _id: id, deleted_at: null }, { deleted_at: Date.now() }, { new: true })
164
+ .lean()
165
+ .exec();
166
+ if (!employee) {
167
+ res.status(404).json({ message: 'Employee not found' });
168
+ return;
169
+ }
170
+ res.json({
171
+ message: 'Employee deleted successfully',
172
+ employee: {
173
+ id: employee._id,
174
+ first_name: employee.first_name,
175
+ last_name: employee.last_name
176
+ }
177
+ });
178
+ }
179
+ catch (err) {
180
+ console.error('Delete employee error', err);
181
+ res.status(500).json({ message: 'Failed to delete employee', error: String(err) });
182
+ }
183
+ }
184
+ }
185
+ exports.default = Employees;
@@ -0,0 +1,9 @@
1
+ import { Request, Response } from 'express';
2
+ /**
3
+ * Health Check Controller
4
+ * Serves a fancy HTML page to show API is running
5
+ */
6
+ export declare class HealthController {
7
+ healthCheck(req: Request, res: Response): Promise<void>;
8
+ }
9
+ export default HealthController;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.HealthController = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ /**
10
+ * Health Check Controller
11
+ * Serves a fancy HTML page to show API is running
12
+ */
13
+ class HealthController {
14
+ async healthCheck(req, res) {
15
+ try {
16
+ // Get the path to the HTML file
17
+ const htmlPath = path_1.default.join(__dirname, '../../../public/health.html');
18
+ // Read the HTML file
19
+ const htmlContent = fs_1.default.readFileSync(htmlPath, 'utf8');
20
+ // Set appropriate headers
21
+ res.setHeader('Content-Type', 'text/html');
22
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
23
+ res.setHeader('Pragma', 'no-cache');
24
+ res.setHeader('Expires', '0');
25
+ // Send the HTML content
26
+ res.status(200).send(htmlContent);
27
+ }
28
+ catch (error) {
29
+ console.error('Health check error:', error);
30
+ // If HTML file not found, return simple JSON response
31
+ res.status(500).json({
32
+ status: 'error',
33
+ message: 'Health check page unavailable',
34
+ timestamp: new Date().toISOString(),
35
+ api: 'Inventory Management System',
36
+ version: '1.0.0'
37
+ });
38
+ }
39
+ }
40
+ }
41
+ exports.HealthController = HealthController;
42
+ exports.default = HealthController;
@@ -0,0 +1,16 @@
1
+ import EmployeesController from './employees';
2
+ import UsersController from './users';
3
+ import { ModulesController } from './modules';
4
+ import { AuthController } from './auth';
5
+ import { HealthController } from './health';
6
+ import MeetingsController from './meetings';
7
+ export { EmployeesController, UsersController, ModulesController, AuthController, HealthController, MeetingsController };
8
+ declare const _default: {
9
+ EmployeesController: typeof EmployeesController;
10
+ UsersController: typeof UsersController;
11
+ ModulesController: typeof ModulesController;
12
+ AuthController: typeof AuthController;
13
+ HealthController: typeof HealthController;
14
+ MeetingsController: typeof MeetingsController;
15
+ };
16
+ export default _default;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MeetingsController = exports.HealthController = exports.AuthController = exports.ModulesController = exports.UsersController = exports.EmployeesController = void 0;
7
+ const employees_1 = __importDefault(require("./employees"));
8
+ exports.EmployeesController = employees_1.default;
9
+ const users_1 = __importDefault(require("./users"));
10
+ exports.UsersController = users_1.default;
11
+ const modules_1 = require("./modules");
12
+ Object.defineProperty(exports, "ModulesController", { enumerable: true, get: function () { return modules_1.ModulesController; } });
13
+ const auth_1 = require("./auth");
14
+ Object.defineProperty(exports, "AuthController", { enumerable: true, get: function () { return auth_1.AuthController; } });
15
+ const health_1 = require("./health");
16
+ Object.defineProperty(exports, "HealthController", { enumerable: true, get: function () { return health_1.HealthController; } });
17
+ const meetings_1 = __importDefault(require("./meetings"));
18
+ exports.MeetingsController = meetings_1.default;
19
+ exports.default = { EmployeesController: employees_1.default, UsersController: users_1.default, ModulesController: modules_1.ModulesController, AuthController: auth_1.AuthController, HealthController: health_1.HealthController, MeetingsController: meetings_1.default };
@@ -0,0 +1,23 @@
1
+ declare class Meetings {
2
+ /**
3
+ * Create a new meeting
4
+ */
5
+ static create(req: any, res: any): Promise<void>;
6
+ /**
7
+ * Join a meeting
8
+ */
9
+ static join(req: any, res: any): Promise<void>;
10
+ /**
11
+ * Leave a meeting
12
+ */
13
+ static leave(req: any, res: any): Promise<void>;
14
+ /**
15
+ * Get user's meetings
16
+ */
17
+ static getMyMeetings(req: any, res: any): Promise<void>;
18
+ /**
19
+ * Get meeting details
20
+ */
21
+ static getMeeting(req: any, res: any): Promise<void>;
22
+ }
23
+ export default Meetings;
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const models_1 = require("../../models");
4
+ // import { canJoinMeeting } from '../middlewares/meeting';
5
+ // import { sendNotification, sendMeetingInvitation } from '../utils/notifications';
6
+ class Meetings {
7
+ /**
8
+ * Create a new meeting
9
+ */
10
+ static async create(req, res) {
11
+ try {
12
+ const { title, description, meeting_type = 'video', scheduled_at, participants, max_participants = 50 } = req.body;
13
+ const userId = req.user.userId;
14
+ // Generate unique meeting URL
15
+ const meeting_url = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
16
+ // Process participants - handle both user IDs and email objects
17
+ const participantsArray = [];
18
+ if (Array.isArray(participants)) {
19
+ for (const participant of participants) {
20
+ if (typeof participant === 'string') {
21
+ // Check if it's an email or user ID
22
+ if (participant.includes('@')) {
23
+ // Email provided - try to find user or store email
24
+ const user = await models_1.Users.findOne({ email: participant.toLowerCase(), deleted_at: null }).lean().exec();
25
+ if (user) {
26
+ participantsArray.push({
27
+ user_id: user._id,
28
+ is_active: false
29
+ });
30
+ }
31
+ else {
32
+ // User doesn't exist - store as pending invitation
33
+ participantsArray.push({
34
+ email: participant,
35
+ is_active: false,
36
+ status: 'pending'
37
+ });
38
+ }
39
+ }
40
+ else {
41
+ // Direct user ID
42
+ participantsArray.push({
43
+ user_id: participant,
44
+ is_active: false
45
+ });
46
+ }
47
+ }
48
+ else if (typeof participant === 'object' && participant !== null) {
49
+ // Object with id or email
50
+ if (participant.id) {
51
+ participantsArray.push({
52
+ user_id: participant.id,
53
+ is_active: false
54
+ });
55
+ }
56
+ else if (participant.email) {
57
+ // Email provided - try to find user or store email
58
+ const user = await models_1.Users.findOne({ email: participant.email.toLowerCase(), deleted_at: null }).lean().exec();
59
+ if (user) {
60
+ participantsArray.push({
61
+ user_id: user._id,
62
+ is_active: false
63
+ });
64
+ }
65
+ else {
66
+ // User doesn't exist - store as pending invitation (could be enhanced later)
67
+ participantsArray.push({
68
+ email: participant.email,
69
+ is_active: false,
70
+ status: 'pending'
71
+ });
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ const meeting = new models_1.Meetings({
78
+ title,
79
+ description,
80
+ host_id: userId,
81
+ meeting_type,
82
+ scheduled_at: scheduled_at ? new Date(scheduled_at).getTime() : Date.now(),
83
+ max_participants,
84
+ meeting_url,
85
+ participants: participantsArray
86
+ });
87
+ await meeting.save();
88
+ await meeting.populate('host_id', 'first_name last_name email');
89
+ await meeting.populate('participants.user_id', 'first_name last_name email');
90
+ // Send notifications to participants
91
+ // if (participants && participants.length > 0) {
92
+ // await sendMeetingInvitation(meeting._id, participants, title, description, userId);
93
+ // }
94
+ res.status(201).json({ success: true, meeting });
95
+ }
96
+ catch (error) {
97
+ console.error('Error creating meeting:', error);
98
+ res.status(500).json({ error: 'Failed to create meeting' });
99
+ }
100
+ }
101
+ /**
102
+ * Join a meeting
103
+ */
104
+ static async join(req, res) {
105
+ try {
106
+ const { meetingId } = req.params;
107
+ const userId = req.user.userId;
108
+ const meeting = req.meeting;
109
+ // Mark user as active participant
110
+ const participantIndex = meeting.participants.findIndex((p) => p.user_id.toString() === userId);
111
+ if (participantIndex !== -1) {
112
+ meeting.participants[participantIndex].is_active = true;
113
+ meeting.participants[participantIndex].joined_at = Date.now();
114
+ }
115
+ // Start meeting if not started
116
+ if (!meeting.started_at) {
117
+ meeting.started_at = Date.now();
118
+ }
119
+ await meeting.save();
120
+ // Notify other participants
121
+ const otherParticipants = meeting.participants
122
+ .filter((p) => p.user_id.toString() !== userId && p.is_active)
123
+ .map((p) => p.user_id.toString());
124
+ // if (otherParticipants.length > 0) {
125
+ // await sendNotification(
126
+ // otherParticipants,
127
+ // 'User Joined Meeting',
128
+ // `${req.user.email} has joined the meeting`,
129
+ // { type: 'user_joined', userId, meetingId },
130
+ // 'meeting_update'
131
+ // );
132
+ // }
133
+ res.json({ success: true, meeting_url: meeting.meeting_url });
134
+ }
135
+ catch (error) {
136
+ console.error('Error joining meeting:', error);
137
+ res.status(500).json({ error: 'Failed to join meeting' });
138
+ }
139
+ }
140
+ /**
141
+ * Leave a meeting
142
+ */
143
+ static async leave(req, res) {
144
+ try {
145
+ const { meetingId } = req.params;
146
+ const userId = req.user.userId;
147
+ const meeting = req.meeting;
148
+ // Mark user as inactive participant
149
+ const participantIndex = meeting.participants.findIndex((p) => p.user_id.toString() === userId);
150
+ if (participantIndex !== -1) {
151
+ meeting.participants[participantIndex].is_active = false;
152
+ meeting.participants[participantIndex].left_at = Date.now();
153
+ }
154
+ // Check if meeting should end (only host left or no active participants)
155
+ const isHost = meeting.host_id.toString() === userId;
156
+ const activeParticipants = meeting.participants.filter((p) => p.is_active);
157
+ if (isHost || activeParticipants.length === 0) {
158
+ meeting.ended_at = Date.now();
159
+ meeting.is_active = false;
160
+ }
161
+ await meeting.save();
162
+ // Notify other participants
163
+ const remainingParticipants = activeParticipants
164
+ .filter((p) => p.user_id.toString() !== userId)
165
+ .map((p) => p.user_id.toString());
166
+ // if (remainingParticipants.length > 0) {
167
+ // await sendNotification(
168
+ // remainingParticipants,
169
+ // 'User Left Meeting',
170
+ // `${req.user.email} has left the meeting`,
171
+ // { type: 'user_left', userId, meetingId },
172
+ // 'meeting_update'
173
+ // );
174
+ // }
175
+ res.json({ success: true });
176
+ }
177
+ catch (error) {
178
+ console.error('Error leaving meeting:', error);
179
+ res.status(500).json({ error: 'Failed to leave meeting' });
180
+ }
181
+ }
182
+ /**
183
+ * Get user's meetings
184
+ */
185
+ static async getMyMeetings(req, res) {
186
+ try {
187
+ const userId = req.user.userId;
188
+ const { status = 'upcoming' } = req.query;
189
+ let filter = {
190
+ $or: [
191
+ { host_id: userId },
192
+ { 'participants.user_id': userId }
193
+ ]
194
+ };
195
+ if (status === 'upcoming') {
196
+ filter.scheduled_at = { $gt: Date.now() };
197
+ }
198
+ else if (status === 'ongoing') {
199
+ filter.started_at = { $ne: null };
200
+ filter.ended_at = null;
201
+ filter.is_active = true;
202
+ }
203
+ else if (status === 'completed') {
204
+ filter.ended_at = { $ne: null };
205
+ }
206
+ const meetings = await models_1.Meetings.find(filter)
207
+ .populate('host_id', 'first_name last_name email')
208
+ .populate('participants.user_id', 'first_name last_name email')
209
+ .sort({ scheduled_at: -1 });
210
+ res.json({ success: true, meetings });
211
+ }
212
+ catch (error) {
213
+ console.error('Error fetching meetings:', error);
214
+ res.status(500).json({ error: 'Failed to fetch meetings' });
215
+ }
216
+ }
217
+ /**
218
+ * Get meeting details
219
+ */
220
+ static async getMeeting(req, res) {
221
+ try {
222
+ const meeting = req.meeting;
223
+ await meeting.populate('host_id', 'first_name last_name email');
224
+ await meeting.populate('participants.user_id', 'first_name last_name email');
225
+ res.json({ success: true, meeting });
226
+ }
227
+ catch (error) {
228
+ console.error('Error fetching meeting:', error);
229
+ res.status(500).json({ error: 'Failed to fetch meeting' });
230
+ }
231
+ }
232
+ }
233
+ exports.default = Meetings;
@@ -0,0 +1,5 @@
1
+ import { Request, Response } from 'express';
2
+ export declare class ModulesController {
3
+ getModules(req: Request, res: Response): Promise<void>;
4
+ runSeeders(req: Request, res: Response): Promise<void>;
5
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ModulesController = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const seeder_1 = require("../../database/seeder");
40
+ class ModulesController {
41
+ async getModules(req, res) {
42
+ try {
43
+ // Try multiple possible paths for modules.json
44
+ let modulesPath;
45
+ // List of possible paths to check
46
+ const possiblePaths = [
47
+ // Development path
48
+ path.join(__dirname, '../data/modules.json'),
49
+ // Production path (when called from user-api)
50
+ path.join(__dirname, '../../data/modules.json'),
51
+ // Alternative production path
52
+ path.join(__dirname, '../../../backend/src/data/modules.json'),
53
+ // Relative to backend project root
54
+ path.join(process.cwd(), 'src/data/modules.json'),
55
+ // Relative to backend project root (dist)
56
+ path.join(process.cwd(), 'dist/data/modules.json'),
57
+ // Absolute path fallback
58
+ '/Users/abdegracia/aldrin-degracia/code/rnd/inventory-management-system/backend/src/data/modules.json'
59
+ ];
60
+ // Find the first existing path
61
+ for (const testPath of possiblePaths) {
62
+ if (fs.existsSync(testPath)) {
63
+ modulesPath = testPath;
64
+ break;
65
+ }
66
+ }
67
+ if (!modulesPath) {
68
+ throw new Error('modules.json file not found in any expected location');
69
+ }
70
+ const modulesData = JSON.parse(fs.readFileSync(modulesPath, 'utf-8'));
71
+ res.json({
72
+ success: true,
73
+ data: modulesData
74
+ });
75
+ }
76
+ catch (error) {
77
+ console.error('Error reading modules data:', error);
78
+ res.status(500).json({
79
+ success: false,
80
+ message: 'Failed to load modules data',
81
+ error: String(error)
82
+ });
83
+ }
84
+ }
85
+ async runSeeders(req, res) {
86
+ try {
87
+ console.log('Running seeders via API call...');
88
+ await (0, seeder_1.runSeeders)();
89
+ res.json({
90
+ success: true,
91
+ message: 'Seeders executed successfully'
92
+ });
93
+ }
94
+ catch (error) {
95
+ console.error('Error running seeders:', error);
96
+ res.status(500).json({
97
+ success: false,
98
+ message: 'Failed to run seeders',
99
+ error: String(error)
100
+ });
101
+ }
102
+ }
103
+ }
104
+ exports.ModulesController = ModulesController;