powr-sdk-api 4.1.10 → 4.3.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 (46) hide show
  1. package/dist/index.js +7 -5
  2. package/dist/{services → managers}/functions.js +1 -1
  3. package/dist/managers/index.js +26 -0
  4. package/dist/{services/scheduledTasks.js → managers/tasks.js} +123 -143
  5. package/dist/{services → managers}/tools.js +1 -1
  6. package/dist/middleware/projectId.js +1 -1
  7. package/dist/routes/functions.js +3 -1
  8. package/dist/routes/index.js +3 -27
  9. package/dist/routes/tasks.js +304 -0
  10. package/dist/routes/tools.js +21 -8
  11. package/package.json +69 -71
  12. package/dist/admin/activities.js +0 -81
  13. package/dist/admin/auth.js +0 -234
  14. package/dist/admin/blogs.js +0 -94
  15. package/dist/admin/comments.js +0 -83
  16. package/dist/admin/files.js +0 -56
  17. package/dist/admin/forms.js +0 -242
  18. package/dist/admin/index.js +0 -53
  19. package/dist/admin/invoice.js +0 -163
  20. package/dist/admin/likes.js +0 -126
  21. package/dist/admin/notifications.js +0 -93
  22. package/dist/admin/plexx.js +0 -53
  23. package/dist/admin/ratings.js +0 -189
  24. package/dist/admin/routes.js +0 -132
  25. package/dist/admin/slides.js +0 -101
  26. package/dist/admin/users.js +0 -175
  27. package/dist/admin/waitlists.js +0 -94
  28. package/dist/logger/gcs.js +0 -78
  29. package/dist/logger/s3.js +0 -78
  30. package/dist/middleware/auth.js +0 -76
  31. package/dist/middleware/logger.js +0 -45
  32. package/dist/middleware/response.js +0 -53
  33. package/dist/routes/admin/index.js +0 -520
  34. package/dist/routes/blogs.js +0 -94
  35. package/dist/routes/invoice.js +0 -167
  36. package/dist/routes/plexx.js +0 -269
  37. package/dist/routes/routes.js +0 -143
  38. package/dist/routes/scheduledTasks.js +0 -240
  39. package/dist/scripts/update-tools-schema.js +0 -157
  40. package/dist/services/dbService.js +0 -42
  41. package/dist/services/logger.js +0 -35
  42. package/dist/services/plexx.js +0 -229
  43. package/dist/utils/auth.js +0 -19
  44. package/dist/utils/logger.js +0 -57
  45. package/dist/utils/s3-transport.js +0 -61
  46. package/dist/utils/s3.js +0 -78
package/dist/index.js CHANGED
@@ -14,11 +14,13 @@ const {
14
14
  createSwaggerSpec
15
15
  } = require("./swagger");
16
16
  const {
17
- createPowrRoutes,
17
+ createPowrRoutes
18
+ } = require("./routes");
19
+ const {
18
20
  initializeFunctions,
19
21
  initializeTools,
20
- initializeScheduledTasks
21
- } = require("./routes");
22
+ executeTasks
23
+ } = require("./managers");
22
24
  const {
23
25
  verifyToken
24
26
  } = require("./middleware/jwtToken");
@@ -31,6 +33,6 @@ module.exports = {
31
33
  createPowrRoutes,
32
34
  initializeFunctions,
33
35
  initializeTools,
34
- initializeScheduledTasks,
35
- verifyToken
36
+ verifyToken,
37
+ executeTasks
36
38
  };
@@ -2,7 +2,7 @@
2
2
 
3
3
  const {
4
4
  getDb
5
- } = require("./mongo");
5
+ } = require("../services/mongo");
6
6
  const crypto = require('crypto');
7
7
  const config = require('../config');
8
8
  class FunctionsManager {
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ const functionsManager = require('./functions');
4
+ const toolsManager = require('./tools');
5
+ const scheduledTasksManager = require('./tasks');
6
+
7
+ // Async Functions initialization function
8
+ const initializeFunctions = async (options = {}) => {
9
+ // Initialize Functions manager with options
10
+ await functionsManager.initialize(options);
11
+ };
12
+
13
+ // Async Tools initialization function
14
+ const initializeTools = async (options = {}) => {
15
+ // Initialize Tools manager with options
16
+ await toolsManager.initialize(options);
17
+ };
18
+ module.exports = {
19
+ // Managers
20
+ functionsManager,
21
+ toolsManager,
22
+ scheduledTasksManager,
23
+ // Initialization/Execution methods
24
+ initializeFunctions,
25
+ initializeTools
26
+ };
@@ -2,64 +2,44 @@
2
2
 
3
3
  const {
4
4
  getDb
5
- } = require("./mongo");
6
- const cron = require('node-cron');
5
+ } = require("../services/mongo");
7
6
  class ScheduledTasksManager {
8
- constructor() {
9
- this.scheduledJobs = new Map();
10
- this.isInitialized = false;
11
- }
12
- async initialize() {
13
- try {
14
- console.log("📅 Initializing scheduled tasks manager...");
15
-
16
- // Load existing tasks from database
17
- const db = await getDb();
18
- const tasks = await db.collection("scheduled_tasks").find({
19
- isActive: true
20
- }).toArray();
21
-
22
- // Schedule existing active tasks
23
- tasks.forEach(task => {
24
- this.scheduleTask(task);
25
- });
26
- this.isInitialized = true;
27
- console.log(`✅ Scheduled ${tasks.length} active tasks`);
28
- } catch (error) {
29
- console.error("❌ Failed to initialize scheduled tasks:", error);
30
- this.isInitialized = true; // Still mark as initialized
31
- }
32
- }
33
-
34
7
  // Create a new scheduled task
35
8
  async createTask(taskData) {
36
9
  try {
37
10
  const db = await getDb();
38
11
  const task = {
39
- id: taskData.id || this.generateTaskId(),
40
12
  name: taskData.name,
41
13
  description: taskData.description,
42
- cronExpression: taskData.cronExpression,
43
14
  toolId: taskData.toolId,
44
15
  actionId: taskData.actionId,
45
16
  params: taskData.params,
46
17
  userId: taskData.userId,
47
18
  projectId: taskData.projectId,
48
- // Add projectId
49
19
  isActive: taskData.isActive !== false,
50
20
  // Default to true
51
- lastRun: null,
52
- nextRun: this.getNextRunTime(taskData.cronExpression),
21
+ scheduledFor: taskData.scheduledFor,
22
+ // null, timestamp, or cron expression
23
+ nextRun: null,
24
+ // Will be calculated based on scheduling type
53
25
  createdAt: new Date(),
54
26
  updatedAt: new Date()
55
27
  };
56
- await db.collection("scheduled_tasks").insertOne(task);
57
28
 
58
- // Schedule the task if it's active
59
- if (task.isActive) {
60
- this.scheduleTask(task);
29
+ // Calculate nextRun based on scheduling type
30
+ if (!task.scheduledFor) {
31
+ // Immediate execution - run on next Atlas trigger
32
+ task.nextRun = new Date();
33
+ } else if (this.isTimestamp(task.scheduledFor)) {
34
+ // One-time execution - run at the specified time
35
+ task.nextRun = new Date(task.scheduledFor);
36
+ } else if (this.isCronExpression(task.scheduledFor)) {
37
+ // Recurring execution - calculate next run from cron
38
+ task.nextRun = this.getNextRunTime(task.scheduledFor);
61
39
  }
40
+ await db.collection("tasks").insertOne(task);
62
41
  console.log(`✅ Created scheduled task: ${task.name} (${task.id})`);
42
+ console.log(`📅 Next run: ${task.nextRun}`);
63
43
  return {
64
44
  success: true,
65
45
  task
@@ -88,7 +68,7 @@ class ScheduledTasksManager {
88
68
  query.userId = userId;
89
69
  query.projectId = projectId;
90
70
  }
91
- const tasks = await db.collection("scheduled_tasks").find(query).sort({
71
+ const tasks = await db.collection("tasks").find(query).sort({
92
72
  createdAt: -1
93
73
  }).toArray();
94
74
  return {
@@ -121,7 +101,7 @@ class ScheduledTasksManager {
121
101
  query.userId = userId;
122
102
  query.projectId = projectId;
123
103
  }
124
- const task = await db.collection("scheduled_tasks").findOne(query);
104
+ const task = await db.collection("tasks").findOne(query);
125
105
  if (!task) {
126
106
  return {
127
107
  success: false,
@@ -142,7 +122,7 @@ class ScheduledTasksManager {
142
122
  }
143
123
 
144
124
  // Update a task (with project and user validation)
145
- async updateTask(taskId, userId, projectId, updates, isAdmin = false) {
125
+ async updateTask(taskId, userId, projectId, updateData, isAdmin = false) {
146
126
  try {
147
127
  const db = await getDb();
148
128
 
@@ -158,42 +138,31 @@ class ScheduledTasksManager {
158
138
  query.userId = userId;
159
139
  query.projectId = projectId;
160
140
  }
161
-
162
- // Get existing task
163
- const existingTask = await db.collection("scheduled_tasks").findOne(query);
164
- if (!existingTask) {
141
+ const task = await db.collection("tasks").findOne(query);
142
+ if (!task) {
165
143
  return {
166
144
  success: false,
167
145
  message: "Task not found"
168
146
  };
169
147
  }
170
148
 
171
- // Update fields
172
- const updatedTask = {
173
- ...existingTask,
174
- ...updates,
175
- updatedAt: new Date()
176
- };
177
-
178
- // Update next run time if cron expression changed
179
- if (updates.cronExpression && updates.cronExpression !== existingTask.cronExpression) {
180
- updatedTask.nextRun = this.getNextRunTime(updates.cronExpression);
181
- }
182
- await db.collection("scheduled_tasks").updateOne(query, {
183
- $set: updatedTask
149
+ // Update the task
150
+ const updateResult = await db.collection("tasks").updateOne(query, {
151
+ $set: {
152
+ ...updateData,
153
+ updatedAt: new Date(),
154
+ nextRun: updateData.scheduledFor ? this.getNextRunTime(updateData.scheduledFor) : task.nextRun
155
+ }
184
156
  });
185
-
186
- // Reschedule if active
187
- if (updatedTask.isActive) {
188
- this.unscheduleTask(taskId);
189
- this.scheduleTask(updatedTask);
190
- } else {
191
- this.unscheduleTask(taskId);
157
+ if (updateResult.modifiedCount === 0) {
158
+ return {
159
+ success: false,
160
+ message: "Failed to update task"
161
+ };
192
162
  }
193
- console.log(`✅ Updated scheduled task: ${updatedTask.name} (${taskId})`);
163
+ console.log(`✅ Updated scheduled task: ${taskId}`);
194
164
  return {
195
- success: true,
196
- task: updatedTask
165
+ success: true
197
166
  };
198
167
  } catch (error) {
199
168
  console.error("❌ Failed to update scheduled task:", error);
@@ -223,7 +192,7 @@ class ScheduledTasksManager {
223
192
  }
224
193
 
225
194
  // Get task to check if it exists
226
- const task = await db.collection("scheduled_tasks").findOne(query);
195
+ const task = await db.collection("tasks").findOne(query);
227
196
  if (!task) {
228
197
  return {
229
198
  success: false,
@@ -232,10 +201,10 @@ class ScheduledTasksManager {
232
201
  }
233
202
 
234
203
  // Remove from database
235
- await db.collection("scheduled_tasks").deleteOne(query);
204
+ await db.collection("tasks").deleteOne(query);
205
+
206
+ // No need to unschedule - MongoDB Atlas will handle this automatically
236
207
 
237
- // Unschedule the task
238
- this.unscheduleTask(taskId);
239
208
  console.log(`✅ Deleted scheduled task: ${task.name} (${taskId})`);
240
209
  return {
241
210
  success: true
@@ -266,36 +235,23 @@ class ScheduledTasksManager {
266
235
  query.userId = userId;
267
236
  query.projectId = projectId;
268
237
  }
269
- const task = await db.collection("scheduled_tasks").findOne(query);
238
+ const task = await db.collection("tasks").findOne(query);
270
239
  if (!task) {
271
240
  return {
272
241
  success: false,
273
242
  message: "Task not found"
274
243
  };
275
244
  }
276
- if (isActive) {
277
- // Activate task
278
- await db.collection("scheduled_tasks").updateOne(query, {
279
- $set: {
280
- isActive: true,
281
- updatedAt: new Date()
282
- }
283
- });
284
- this.scheduleTask({
285
- ...task,
286
- isActive: true
287
- });
288
- } else {
289
- // Deactivate task
290
- await db.collection("scheduled_tasks").updateOne(query, {
291
- $set: {
292
- isActive: false,
293
- updatedAt: new Date()
294
- }
295
- });
296
- this.unscheduleTask(taskId);
297
- }
245
+
246
+ // Update active status
247
+ await db.collection("tasks").updateOne(query, {
248
+ $set: {
249
+ isActive: isActive,
250
+ updatedAt: new Date()
251
+ }
252
+ });
298
253
  console.log(`${isActive ? '✅' : '❌'} Task ${taskId} ${isActive ? 'activated' : 'deactivated'}`);
254
+ console.log(`📅 MongoDB Atlas Scheduled Trigger will ${isActive ? 'start' : 'stop'} executing this task.`);
299
255
  return {
300
256
  success: true
301
257
  };
@@ -325,7 +281,7 @@ class ScheduledTasksManager {
325
281
  query.userId = userId;
326
282
  query.projectId = projectId;
327
283
  }
328
- const task = await db.collection("scheduled_tasks").findOne(query);
284
+ const task = await db.collection("tasks").findOne(query);
329
285
  if (!task) {
330
286
  return {
331
287
  success: false,
@@ -336,13 +292,6 @@ class ScheduledTasksManager {
336
292
 
337
293
  // Execute the task
338
294
  const result = await this.executeTaskAction(task);
339
-
340
- // Update last run time
341
- await db.collection("scheduled_tasks").updateOne(query, {
342
- $set: {
343
- lastRun: new Date()
344
- }
345
- });
346
295
  return {
347
296
  success: true,
348
297
  result
@@ -356,37 +305,57 @@ class ScheduledTasksManager {
356
305
  }
357
306
  }
358
307
 
359
- // Schedule a task
360
- scheduleTask(task) {
308
+ // Execute scheduled tasks (called by MongoDB Atlas Scheduled Trigger)
309
+ async executeScheduledTasks(projectId) {
361
310
  try {
362
- // Unschedule if already scheduled
363
- this.unscheduleTask(task.id);
364
-
365
- // Validate cron expression
366
- if (!cron.validate(task.cronExpression)) {
367
- console.error(`❌ Invalid cron expression for task ${task.id}: ${task.cronExpression}`);
368
- return;
311
+ const db = await getDb();
312
+ const query = {
313
+ projectId: projectId,
314
+ isActive: true,
315
+ nextRun: {
316
+ $lte: new Date()
317
+ } // Only tasks where nextRun <= current time
318
+ };
319
+ const tasks = await db.collection("tasks").find(query).toArray();
320
+ for (const task of tasks) {
321
+ try {
322
+ console.log(`⏰ Executing: ${task.name} (${task.id}) for project ${task.projectId}`);
323
+
324
+ // Execute the task directly (we already have the task data)
325
+ const result = await this.executeTaskAction(task);
326
+
327
+ // Handle task completion and next run time in single update
328
+ const updateData = {};
329
+ if (!task.scheduledFor || this.isTimestamp(task.scheduledFor)) {
330
+ // For immediate and one-time tasks, deactivate after execution
331
+ updateData.isActive = false;
332
+ console.log(`✅ Task ${task.id} completed and deactivated`);
333
+ } else if (this.isCronExpression(task.scheduledFor)) {
334
+ // For recurring tasks, calculate next run time
335
+ updateData.nextRun = this.getNextRunTime(task.scheduledFor);
336
+ console.log(`📅 Updated next run time for task ${task.id}: ${updateData.nextRun}`);
337
+ }
338
+ await db.collection("tasks").updateOne({
339
+ id: task.id
340
+ }, {
341
+ $set: updateData
342
+ });
343
+ console.log(`✅ Task ${task.id} completed:`, result.success ? 'SUCCESS' : 'FAILED');
344
+ } catch (error) {
345
+ console.error(`❌ Task ${task.id} failed:`, error.message);
346
+ }
369
347
  }
370
-
371
- // Schedule the task
372
- const job = cron.schedule(task.cronExpression, async () => {
373
- console.log(`⏰ Executing scheduled task: ${task.name} (${task.id})`);
374
- await this.executeTaskAction(task);
375
- });
376
- this.scheduledJobs.set(task.id, job);
377
- console.log(`✅ Scheduled task: ${task.name} (${task.id})`);
348
+ return {
349
+ success: true,
350
+ tasksExecuted: tasks.length,
351
+ projectId: projectId
352
+ };
378
353
  } catch (error) {
379
- console.error(`❌ Failed to schedule task ${task.id}:`, error);
380
- }
381
- }
382
-
383
- // Unschedule a task
384
- unscheduleTask(taskId) {
385
- const job = this.scheduledJobs.get(taskId);
386
- if (job) {
387
- job.stop();
388
- this.scheduledJobs.delete(taskId);
389
- console.log(`🛑 Unscheduled task: ${taskId}`);
354
+ console.error("❌ Failed to execute scheduled tasks:", error);
355
+ return {
356
+ success: false,
357
+ error: error.message
358
+ };
390
359
  }
391
360
  }
392
361
 
@@ -394,7 +363,9 @@ class ScheduledTasksManager {
394
363
  async executeTaskAction(task) {
395
364
  try {
396
365
  // Import tools manager
397
- const toolsManager = require('./tools');
366
+ const {
367
+ toolsManager
368
+ } = require('./index');
398
369
 
399
370
  // Execute the tool action
400
371
  const result = await toolsManager.executeToolAction(task.userId, task.toolId, task.actionId, task.params);
@@ -429,10 +400,28 @@ class ScheduledTasksManager {
429
400
  }
430
401
  }
431
402
 
432
- // Helper methods
433
- generateTaskId() {
434
- return `task_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
403
+ // Check if a string is a valid timestamp
404
+ isTimestamp(value) {
405
+ try {
406
+ const date = new Date(value);
407
+ return !isNaN(date.getTime()) && value !== date.toISOString().slice(0, 10); // Not just a date
408
+ } catch (error) {
409
+ return false;
410
+ }
411
+ }
412
+
413
+ // Check if a string is a cron expression
414
+ isCronExpression(value) {
415
+ try {
416
+ const parser = require('cron-parser');
417
+ parser.parseExpression(value);
418
+ return true;
419
+ } catch (error) {
420
+ return false;
421
+ }
435
422
  }
423
+
424
+ // Get next run time for cron expression
436
425
  getNextRunTime(cronExpression) {
437
426
  try {
438
427
  const parser = require('cron-parser');
@@ -443,15 +432,6 @@ class ScheduledTasksManager {
443
432
  return null;
444
433
  }
445
434
  }
446
-
447
- // Get statistics
448
- getStats() {
449
- return {
450
- isInitialized: this.isInitialized,
451
- activeJobs: this.scheduledJobs.size,
452
- totalJobs: this.scheduledJobs.size
453
- };
454
- }
455
435
  }
456
436
 
457
437
  // Create and export singleton instance
@@ -2,7 +2,7 @@
2
2
 
3
3
  const {
4
4
  getDb
5
- } = require("./mongo");
5
+ } = require("../services/mongo");
6
6
  const crypto = require('crypto');
7
7
  const config = require('../config');
8
8
  class ToolsManager {
@@ -11,7 +11,7 @@ const config = require('../config');
11
11
  */
12
12
  const injectProjectId = (options = {}) => {
13
13
  const isCentralService = options.isCentralService || false;
14
- const excludePaths = options.excludePaths || ['/auth/login', '/auth/register', '/health'];
14
+ const excludePaths = options.excludePaths || ['/health'];
15
15
  return (req, res, next) => {
16
16
  try {
17
17
  // Skip validation for excluded paths
@@ -2,7 +2,9 @@
2
2
 
3
3
  const express = require("express");
4
4
  const router = express.Router();
5
- const functionsManager = require("../services/functions");
5
+ const {
6
+ functionsManager
7
+ } = require("../managers");
6
8
  const {
7
9
  getDb
8
10
  } = require("../services/mongo");
@@ -7,9 +7,6 @@ const {
7
7
  const {
8
8
  verifyToken
9
9
  } = require('../middleware/jwtToken');
10
- const functionsManager = require('../services/functions');
11
- const toolsManager = require('../services/tools');
12
- const scheduledTasksManager = require('../services/scheduledTasks');
13
10
 
14
11
  // Import all route modules
15
12
  const commentsRoutes = require('./comments');
@@ -29,7 +26,7 @@ const profilesRoutes = require('./profiles');
29
26
  const chatRoutes = require('./chat');
30
27
  const feedsRoutes = require('./feeds');
31
28
  const toolsRoutes = require('./tools');
32
- const scheduledTasksRoutes = require('./scheduledTasks');
29
+ const tasksRoutes = require('./tasks');
33
30
 
34
31
  // Synchronous router creation
35
32
  const createPowrRoutes = (options = {}) => {
@@ -54,30 +51,9 @@ const createPowrRoutes = (options = {}) => {
54
51
  router.use('/chat', verifyToken, chatRoutes);
55
52
  router.use('/feeds', verifyToken, feedsRoutes);
56
53
  router.use('/tools', verifyToken, toolsRoutes);
57
- router.use('/scheduled-tasks', verifyToken, scheduledTasksRoutes);
54
+ router.use('/tasks', verifyToken, tasksRoutes);
58
55
  return router;
59
56
  };
60
-
61
- // Async Functions initialization function
62
- const initializeFunctions = async (options = {}) => {
63
- // Initialize Functions manager with options
64
- await functionsManager.initialize(options);
65
- };
66
-
67
- // Async Tools initialization function
68
- const initializeTools = async (options = {}) => {
69
- // Initialize Tools manager with options
70
- await toolsManager.initialize(options);
71
- };
72
-
73
- // Async Scheduled Tasks initialization function
74
- const initializeScheduledTasks = async (options = {}) => {
75
- // Initialize Scheduled Tasks manager with options
76
- await scheduledTasksManager.initialize(options);
77
- };
78
57
  module.exports = {
79
- createPowrRoutes,
80
- initializeFunctions,
81
- initializeTools,
82
- initializeScheduledTasks
58
+ createPowrRoutes
83
59
  };