powr-sdk-api 4.2.0 → 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.
- package/dist/index.js +7 -5
- package/dist/{services → managers}/functions.js +1 -1
- package/dist/managers/index.js +26 -0
- package/dist/{services → managers}/tasks.js +123 -143
- package/dist/{services → managers}/tools.js +1 -1
- package/dist/routes/functions.js +3 -1
- package/dist/routes/index.js +2 -17
- package/dist/routes/tasks.js +184 -63
- package/dist/routes/tools.js +21 -8
- package/package.json +69 -71
- package/dist/admin/activities.js +0 -81
- package/dist/admin/auth.js +0 -234
- package/dist/admin/blogs.js +0 -94
- package/dist/admin/comments.js +0 -83
- package/dist/admin/files.js +0 -56
- package/dist/admin/forms.js +0 -242
- package/dist/admin/index.js +0 -53
- package/dist/admin/invoice.js +0 -163
- package/dist/admin/likes.js +0 -126
- package/dist/admin/notifications.js +0 -93
- package/dist/admin/plexx.js +0 -53
- package/dist/admin/ratings.js +0 -189
- package/dist/admin/routes.js +0 -132
- package/dist/admin/slides.js +0 -101
- package/dist/admin/users.js +0 -175
- package/dist/admin/waitlists.js +0 -94
- package/dist/logger/gcs.js +0 -78
- package/dist/logger/s3.js +0 -78
- package/dist/middleware/auth.js +0 -76
- package/dist/middleware/logger.js +0 -45
- package/dist/middleware/response.js +0 -53
- package/dist/routes/admin/index.js +0 -520
- package/dist/routes/blogs.js +0 -94
- package/dist/routes/invoice.js +0 -167
- package/dist/routes/plexx.js +0 -269
- package/dist/routes/routes.js +0 -143
- package/dist/routes/scheduledTasks.js +0 -240
- package/dist/scripts/update-tools-schema.js +0 -157
- package/dist/services/dbService.js +0 -42
- package/dist/services/logger.js +0 -35
- package/dist/services/plexx.js +0 -229
- package/dist/services/scheduledTasks.js +0 -459
- package/dist/utils/auth.js +0 -19
- package/dist/utils/logger.js +0 -57
- package/dist/utils/s3-transport.js +0 -61
- package/dist/utils/s3.js +0 -78
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const express = require('express');
|
|
4
|
-
const router = express.Router();
|
|
5
|
-
const scheduledTasksManager = require('../services/scheduledTasks');
|
|
6
|
-
const toolsManager = require('../services/tools');
|
|
7
|
-
|
|
8
|
-
// GET /scheduled-tasks - Get all tasks for user
|
|
9
|
-
router.get('/', async (req, res) => {
|
|
10
|
-
try {
|
|
11
|
-
const isAdmin = req.user.role === 'admin';
|
|
12
|
-
const result = await scheduledTasksManager.getUserTasks(req.user.powrId, req.projectId, isAdmin);
|
|
13
|
-
res.json(result);
|
|
14
|
-
} catch (error) {
|
|
15
|
-
console.error('❌ Error getting scheduled tasks:', error);
|
|
16
|
-
res.status(500).json({
|
|
17
|
-
success: false,
|
|
18
|
-
message: 'Failed to get scheduled tasks'
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// GET /scheduled-tasks/:taskId - Get specific task
|
|
24
|
-
router.get('/:taskId', async (req, res) => {
|
|
25
|
-
try {
|
|
26
|
-
const isAdmin = req.user.role === 'admin';
|
|
27
|
-
const result = await scheduledTasksManager.getTask(req.params.taskId, req.user.powrId, req.projectId, isAdmin);
|
|
28
|
-
if (!result.success) {
|
|
29
|
-
return res.status(404).json(result);
|
|
30
|
-
}
|
|
31
|
-
res.json(result);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
console.error('❌ Error getting scheduled task:', error);
|
|
34
|
-
res.status(500).json({
|
|
35
|
-
success: false,
|
|
36
|
-
message: 'Failed to get scheduled task'
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// POST /scheduled-tasks - Create new task
|
|
42
|
-
router.post('/', async (req, res) => {
|
|
43
|
-
try {
|
|
44
|
-
var _tool$actions;
|
|
45
|
-
const {
|
|
46
|
-
name,
|
|
47
|
-
description,
|
|
48
|
-
cronExpression,
|
|
49
|
-
toolId,
|
|
50
|
-
actionId,
|
|
51
|
-
params,
|
|
52
|
-
isActive
|
|
53
|
-
} = req.body;
|
|
54
|
-
|
|
55
|
-
// Validate required fields
|
|
56
|
-
if (!name || !cronExpression || !toolId || !actionId) {
|
|
57
|
-
return res.status(400).json({
|
|
58
|
-
success: false,
|
|
59
|
-
message: 'Missing required fields: name, cronExpression, toolId, actionId'
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Validate tool exists
|
|
64
|
-
const tool = toolsManager.getTool(toolId);
|
|
65
|
-
if (!tool) {
|
|
66
|
-
return res.status(400).json({
|
|
67
|
-
success: false,
|
|
68
|
-
message: `Tool not found: ${toolId}`
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Validate action exists
|
|
73
|
-
const action = (_tool$actions = tool.actions) === null || _tool$actions === void 0 ? void 0 : _tool$actions.find(a => a.id === actionId);
|
|
74
|
-
if (!action) {
|
|
75
|
-
return res.status(400).json({
|
|
76
|
-
success: false,
|
|
77
|
-
message: `Action not found: ${actionId} for tool ${toolId}`
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
const taskData = {
|
|
81
|
-
name,
|
|
82
|
-
description,
|
|
83
|
-
cronExpression,
|
|
84
|
-
toolId,
|
|
85
|
-
actionId,
|
|
86
|
-
params: params || {},
|
|
87
|
-
userId: req.user.powrId,
|
|
88
|
-
projectId: req.projectId,
|
|
89
|
-
// Add projectId
|
|
90
|
-
isActive: isActive !== false // Default to true
|
|
91
|
-
};
|
|
92
|
-
const result = await scheduledTasksManager.createTask(taskData);
|
|
93
|
-
res.status(201).json(result);
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.error('❌ Error creating scheduled task:', error);
|
|
96
|
-
res.status(500).json({
|
|
97
|
-
success: false,
|
|
98
|
-
message: 'Failed to create scheduled task'
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// PUT /scheduled-tasks/:taskId - Update task
|
|
104
|
-
router.put('/:taskId', async (req, res) => {
|
|
105
|
-
try {
|
|
106
|
-
const {
|
|
107
|
-
name,
|
|
108
|
-
description,
|
|
109
|
-
cronExpression,
|
|
110
|
-
toolId,
|
|
111
|
-
actionId,
|
|
112
|
-
params,
|
|
113
|
-
isActive
|
|
114
|
-
} = req.body;
|
|
115
|
-
|
|
116
|
-
// Validate tool exists if toolId is being updated
|
|
117
|
-
if (toolId) {
|
|
118
|
-
const tool = toolsManager.getTool(toolId);
|
|
119
|
-
if (!tool) {
|
|
120
|
-
return res.status(400).json({
|
|
121
|
-
success: false,
|
|
122
|
-
message: `Tool not found: ${toolId}`
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Validate action exists if actionId is being updated
|
|
127
|
-
if (actionId) {
|
|
128
|
-
var _tool$actions2;
|
|
129
|
-
const action = (_tool$actions2 = tool.actions) === null || _tool$actions2 === void 0 ? void 0 : _tool$actions2.find(a => a.id === actionId);
|
|
130
|
-
if (!action) {
|
|
131
|
-
return res.status(400).json({
|
|
132
|
-
success: false,
|
|
133
|
-
message: `Action not found: ${actionId} for tool ${toolId}`
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
const updates = {};
|
|
139
|
-
if (name !== undefined) updates.name = name;
|
|
140
|
-
if (description !== undefined) updates.description = description;
|
|
141
|
-
if (cronExpression !== undefined) updates.cronExpression = cronExpression;
|
|
142
|
-
if (toolId !== undefined) updates.toolId = toolId;
|
|
143
|
-
if (actionId !== undefined) updates.actionId = actionId;
|
|
144
|
-
if (params !== undefined) updates.params = params;
|
|
145
|
-
if (isActive !== undefined) updates.isActive = isActive;
|
|
146
|
-
const isAdmin = req.user.role === 'admin';
|
|
147
|
-
const result = await scheduledTasksManager.updateTask(req.params.taskId, req.user.powrId, req.projectId, updates, isAdmin);
|
|
148
|
-
if (!result.success) {
|
|
149
|
-
return res.status(404).json(result);
|
|
150
|
-
}
|
|
151
|
-
res.json(result);
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error('❌ Error updating scheduled task:', error);
|
|
154
|
-
res.status(500).json({
|
|
155
|
-
success: false,
|
|
156
|
-
message: 'Failed to update scheduled task'
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// DELETE /scheduled-tasks/:taskId - Delete task
|
|
162
|
-
router.delete('/:taskId', async (req, res) => {
|
|
163
|
-
try {
|
|
164
|
-
const isAdmin = req.user.role === 'admin';
|
|
165
|
-
const result = await scheduledTasksManager.deleteTask(req.params.taskId, req.user.powrId, req.projectId, isAdmin);
|
|
166
|
-
if (!result.success) {
|
|
167
|
-
return res.status(404).json(result);
|
|
168
|
-
}
|
|
169
|
-
res.json(result);
|
|
170
|
-
} catch (error) {
|
|
171
|
-
console.error('❌ Error deleting scheduled task:', error);
|
|
172
|
-
res.status(500).json({
|
|
173
|
-
success: false,
|
|
174
|
-
message: 'Failed to delete scheduled task'
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
// POST /scheduled-tasks/:taskId/toggle - Toggle task active status
|
|
180
|
-
router.post('/:taskId/toggle', async (req, res) => {
|
|
181
|
-
try {
|
|
182
|
-
const {
|
|
183
|
-
isActive
|
|
184
|
-
} = req.body;
|
|
185
|
-
if (typeof isActive !== 'boolean') {
|
|
186
|
-
return res.status(400).json({
|
|
187
|
-
success: false,
|
|
188
|
-
message: 'isActive must be a boolean value'
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
const isAdmin = req.user.role === 'admin';
|
|
192
|
-
const result = await scheduledTasksManager.toggleTask(req.params.taskId, req.user.powrId, req.projectId, isActive, isAdmin);
|
|
193
|
-
if (!result.success) {
|
|
194
|
-
return res.status(404).json(result);
|
|
195
|
-
}
|
|
196
|
-
res.json(result);
|
|
197
|
-
} catch (error) {
|
|
198
|
-
console.error('❌ Error toggling scheduled task:', error);
|
|
199
|
-
res.status(500).json({
|
|
200
|
-
success: false,
|
|
201
|
-
message: 'Failed to toggle scheduled task'
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
// POST /scheduled-tasks/:taskId/execute - Execute task manually
|
|
207
|
-
router.post('/:taskId/execute', async (req, res) => {
|
|
208
|
-
try {
|
|
209
|
-
const isAdmin = req.user.role === 'admin';
|
|
210
|
-
const result = await scheduledTasksManager.executeTask(req.params.taskId, req.user.powrId, req.projectId, isAdmin);
|
|
211
|
-
if (!result.success) {
|
|
212
|
-
return res.status(404).json(result);
|
|
213
|
-
}
|
|
214
|
-
res.json(result);
|
|
215
|
-
} catch (error) {
|
|
216
|
-
console.error('❌ Error executing scheduled task:', error);
|
|
217
|
-
res.status(500).json({
|
|
218
|
-
success: false,
|
|
219
|
-
message: 'Failed to execute scheduled task'
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
// GET /scheduled-tasks/stats - Get scheduler statistics
|
|
225
|
-
router.get('/stats', async (req, res) => {
|
|
226
|
-
try {
|
|
227
|
-
const stats = scheduledTasksManager.getStats();
|
|
228
|
-
res.json({
|
|
229
|
-
success: true,
|
|
230
|
-
stats
|
|
231
|
-
});
|
|
232
|
-
} catch (error) {
|
|
233
|
-
console.error('❌ Error getting scheduler stats:', error);
|
|
234
|
-
res.status(500).json({
|
|
235
|
-
success: false,
|
|
236
|
-
message: 'Failed to get scheduler stats'
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
module.exports = router;
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
getDb
|
|
5
|
-
} = require('../services/mongo');
|
|
6
|
-
async function updateToolsSchema() {
|
|
7
|
-
try {
|
|
8
|
-
const db = await getDb();
|
|
9
|
-
|
|
10
|
-
// Update Gmail tool with proper config schema
|
|
11
|
-
await db.collection('tools').updateOne({
|
|
12
|
-
id: 'gmail'
|
|
13
|
-
}, {
|
|
14
|
-
$set: {
|
|
15
|
-
configSchema: {
|
|
16
|
-
email: {
|
|
17
|
-
label: 'Email Address',
|
|
18
|
-
type: 'email',
|
|
19
|
-
required: true,
|
|
20
|
-
placeholder: 'your-email@gmail.com',
|
|
21
|
-
description: 'Your Gmail address'
|
|
22
|
-
},
|
|
23
|
-
appPassword: {
|
|
24
|
-
label: 'App Password',
|
|
25
|
-
type: 'password',
|
|
26
|
-
required: true,
|
|
27
|
-
placeholder: '16-character app password',
|
|
28
|
-
description: 'Gmail App Password (not your regular password)'
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
actions: [{
|
|
32
|
-
id: 'send-email',
|
|
33
|
-
name: 'Send Email',
|
|
34
|
-
description: 'Send an email using Gmail SMTP',
|
|
35
|
-
parameters: {
|
|
36
|
-
to: {
|
|
37
|
-
type: 'string',
|
|
38
|
-
required: true,
|
|
39
|
-
description: 'Recipient email address'
|
|
40
|
-
},
|
|
41
|
-
subject: {
|
|
42
|
-
type: 'string',
|
|
43
|
-
required: true,
|
|
44
|
-
description: 'Email subject'
|
|
45
|
-
},
|
|
46
|
-
body: {
|
|
47
|
-
type: 'string',
|
|
48
|
-
required: true,
|
|
49
|
-
description: 'Email body content'
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}]
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Update Slack tool with proper config schema
|
|
57
|
-
await db.collection('tools').updateOne({
|
|
58
|
-
id: 'slack'
|
|
59
|
-
}, {
|
|
60
|
-
$set: {
|
|
61
|
-
configSchema: {
|
|
62
|
-
botToken: {
|
|
63
|
-
label: 'Bot Token',
|
|
64
|
-
type: 'password',
|
|
65
|
-
required: true,
|
|
66
|
-
placeholder: 'xoxb-your-bot-token',
|
|
67
|
-
description: 'Slack Bot User OAuth Token'
|
|
68
|
-
},
|
|
69
|
-
channelId: {
|
|
70
|
-
label: 'Default Channel ID',
|
|
71
|
-
type: 'text',
|
|
72
|
-
required: false,
|
|
73
|
-
placeholder: 'C1234567890',
|
|
74
|
-
description: 'Default Slack channel ID (optional)'
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
actions: [{
|
|
78
|
-
id: 'send-message',
|
|
79
|
-
name: 'Send Message',
|
|
80
|
-
description: 'Send a message to a Slack channel',
|
|
81
|
-
parameters: {
|
|
82
|
-
channel: {
|
|
83
|
-
type: 'string',
|
|
84
|
-
required: true,
|
|
85
|
-
description: 'Channel ID or name'
|
|
86
|
-
},
|
|
87
|
-
message: {
|
|
88
|
-
type: 'string',
|
|
89
|
-
required: true,
|
|
90
|
-
description: 'Message content'
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}]
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Update GitHub tool with proper config schema
|
|
98
|
-
await db.collection('tools').updateOne({
|
|
99
|
-
id: 'github'
|
|
100
|
-
}, {
|
|
101
|
-
$set: {
|
|
102
|
-
configSchema: {
|
|
103
|
-
accessToken: {
|
|
104
|
-
label: 'Personal Access Token',
|
|
105
|
-
type: 'password',
|
|
106
|
-
required: true,
|
|
107
|
-
placeholder: 'ghp_your-token',
|
|
108
|
-
description: 'GitHub Personal Access Token'
|
|
109
|
-
},
|
|
110
|
-
username: {
|
|
111
|
-
label: 'GitHub Username',
|
|
112
|
-
type: 'text',
|
|
113
|
-
required: true,
|
|
114
|
-
placeholder: 'your-github-username',
|
|
115
|
-
description: 'Your GitHub username'
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
actions: [{
|
|
119
|
-
id: 'create-issue',
|
|
120
|
-
name: 'Create Issue',
|
|
121
|
-
description: 'Create a new issue in a repository',
|
|
122
|
-
parameters: {
|
|
123
|
-
repo: {
|
|
124
|
-
type: 'string',
|
|
125
|
-
required: true,
|
|
126
|
-
description: 'Repository name (owner/repo)'
|
|
127
|
-
},
|
|
128
|
-
title: {
|
|
129
|
-
type: 'string',
|
|
130
|
-
required: true,
|
|
131
|
-
description: 'Issue title'
|
|
132
|
-
},
|
|
133
|
-
body: {
|
|
134
|
-
type: 'string',
|
|
135
|
-
required: false,
|
|
136
|
-
description: 'Issue description'
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}]
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
console.log('✅ Updated tools with proper configuration schemas');
|
|
143
|
-
|
|
144
|
-
// Verify the updates
|
|
145
|
-
const tools = await db.collection('tools').find({}).toArray();
|
|
146
|
-
console.log('📋 Current tools:');
|
|
147
|
-
tools.forEach(tool => {
|
|
148
|
-
var _tool$actions;
|
|
149
|
-
console.log(` - ${tool.name}: ${((_tool$actions = tool.actions) === null || _tool$actions === void 0 ? void 0 : _tool$actions.length) || 0} actions, ${Object.keys(tool.configSchema || {}).length} config fields`);
|
|
150
|
-
});
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.error('❌ Error updating tools schema:', error);
|
|
153
|
-
} finally {
|
|
154
|
-
process.exit(0);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
updateToolsSchema();
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
MongoClient
|
|
5
|
-
} = require('mongodb');
|
|
6
|
-
const {
|
|
7
|
-
config
|
|
8
|
-
} = require('../config');
|
|
9
|
-
const mongoClient = new MongoClient(config.mongoUri, {
|
|
10
|
-
maxPoolSize: 10,
|
|
11
|
-
serverSelectionTimeoutMS: 5000,
|
|
12
|
-
socketTimeoutMS: 45000
|
|
13
|
-
});
|
|
14
|
-
let db;
|
|
15
|
-
async function connect() {
|
|
16
|
-
try {
|
|
17
|
-
await mongoClient.connect();
|
|
18
|
-
db = mongoClient.db();
|
|
19
|
-
console.log("Connected to MongoDB via SDK");
|
|
20
|
-
} catch (error) {
|
|
21
|
-
console.error("Failed to connect to MongoDB:", error);
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
function getDb() {
|
|
26
|
-
if (!db) {
|
|
27
|
-
throw new Error("Database not initialized. Call connectToMongo() first.");
|
|
28
|
-
}
|
|
29
|
-
return db;
|
|
30
|
-
}
|
|
31
|
-
const closeConnection = async () => {
|
|
32
|
-
if (mongoClient) {
|
|
33
|
-
await mongoClient.close();
|
|
34
|
-
db = null;
|
|
35
|
-
console.log('✅ MongoDB connection closed');
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
module.exports = {
|
|
39
|
-
connect,
|
|
40
|
-
getDb,
|
|
41
|
-
closeConnection
|
|
42
|
-
};
|
package/dist/services/logger.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const winston = require('winston');
|
|
4
|
-
const {
|
|
5
|
-
S3Transport
|
|
6
|
-
} = require('../utils/s3');
|
|
7
|
-
|
|
8
|
-
// Custom format for logs
|
|
9
|
-
const logFormat = winston.format.combine(winston.format.timestamp(), winston.format.errors({
|
|
10
|
-
stack: true
|
|
11
|
-
}), winston.format.json());
|
|
12
|
-
|
|
13
|
-
// Create base transports array with console transport
|
|
14
|
-
const transports = [new winston.transports.Console()];
|
|
15
|
-
|
|
16
|
-
// Add S3 transport only in production
|
|
17
|
-
if (process.env.NODE_ENV === 'production') {
|
|
18
|
-
transports.push(new S3Transport({
|
|
19
|
-
bucket: process.env.AWS_LOG_BUCKET_NAME,
|
|
20
|
-
prefix: 'logs',
|
|
21
|
-
bufferSize: 100,
|
|
22
|
-
flushInterval: 5000
|
|
23
|
-
}));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Create the logger
|
|
27
|
-
const logger = winston.createLogger({
|
|
28
|
-
level: process.env.LOG_LEVEL || 'info',
|
|
29
|
-
format: logFormat,
|
|
30
|
-
defaultMeta: {
|
|
31
|
-
service: process.env.LOG_SERVICE_NAME
|
|
32
|
-
},
|
|
33
|
-
transports
|
|
34
|
-
});
|
|
35
|
-
module.exports = logger;
|
package/dist/services/plexx.js
DELETED
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const {
|
|
4
|
-
getDb
|
|
5
|
-
} = require("./mongo");
|
|
6
|
-
const crypto = require('crypto');
|
|
7
|
-
const config = require('../config');
|
|
8
|
-
class PlexxManager {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.compiledFunctions = new Map();
|
|
11
|
-
this.isInitialized = false;
|
|
12
|
-
this.isCentralService = false;
|
|
13
|
-
this.isEnabled = false; // Default disabled
|
|
14
|
-
}
|
|
15
|
-
async initialize(options = {}) {
|
|
16
|
-
this.isCentralService = options.isCentralService || false;
|
|
17
|
-
this.isEnabled = options.enablePlexx === true; // Default false unless explicitly enabled
|
|
18
|
-
|
|
19
|
-
if (!this.isEnabled) {
|
|
20
|
-
console.log("🚫 Plexx is disabled");
|
|
21
|
-
this.isInitialized = true;
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (this.isCentralService) {
|
|
25
|
-
// Central service: Don't pre-load, load dynamically
|
|
26
|
-
console.log("🔄 Central service mode - loading routes dynamically");
|
|
27
|
-
this.isInitialized = true;
|
|
28
|
-
} else {
|
|
29
|
-
// Individual API: Load only this project's routes
|
|
30
|
-
const projectId = config.projectId;
|
|
31
|
-
console.log(`📦 Loading routes for project: ${projectId}`);
|
|
32
|
-
try {
|
|
33
|
-
const db = await getDb();
|
|
34
|
-
const routes = await db.collection("routes").find({
|
|
35
|
-
projectId
|
|
36
|
-
}).toArray();
|
|
37
|
-
routes.forEach(route => {
|
|
38
|
-
this.compileAndCache(route);
|
|
39
|
-
});
|
|
40
|
-
this.isInitialized = true;
|
|
41
|
-
console.log(`✅ Pre-compiled ${routes.length} routes for project ${projectId}`);
|
|
42
|
-
} catch (error) {
|
|
43
|
-
console.error("❌ Failed to initialize routes:", error);
|
|
44
|
-
this.isInitialized = true; // Still mark as initialized to prevent blocking
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
compileAndCache(route) {
|
|
49
|
-
const cacheKey = `${route.projectId}:${route.route}`;
|
|
50
|
-
try {
|
|
51
|
-
// Security validation
|
|
52
|
-
if (!this.validateCode(route.code)) {
|
|
53
|
-
console.error(`❌ Invalid code in route: ${route.route}`);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Pre-compile function
|
|
58
|
-
const compiledFunction = new Function("params", route.code);
|
|
59
|
-
this.compiledFunctions.set(cacheKey, {
|
|
60
|
-
function: compiledFunction,
|
|
61
|
-
metadata: {
|
|
62
|
-
route: route.route,
|
|
63
|
-
projectId: route.projectId,
|
|
64
|
-
compiledAt: new Date(),
|
|
65
|
-
codeHash: this.generateHash(route.code)
|
|
66
|
-
}
|
|
67
|
-
});
|
|
68
|
-
console.log(`✅ Compiled: ${route.route}`);
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error(`❌ Failed to compile ${route.route}:`, error);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
async execute(projectId, route, params) {
|
|
74
|
-
if (!this.isEnabled) {
|
|
75
|
-
return {
|
|
76
|
-
success: false,
|
|
77
|
-
message: "Plexx is disabled",
|
|
78
|
-
data: null
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
const cacheKey = `${projectId}:${route}`;
|
|
82
|
-
const cached = this.compiledFunctions.get(cacheKey);
|
|
83
|
-
if (!cached) {
|
|
84
|
-
if (this.isCentralService) {
|
|
85
|
-
// Try to load only the specific route dynamically
|
|
86
|
-
await this.loadSpecificRoute(projectId, route);
|
|
87
|
-
const retryCached = this.compiledFunctions.get(cacheKey);
|
|
88
|
-
if (retryCached) {
|
|
89
|
-
return retryCached.function(params);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
success: false,
|
|
94
|
-
message: `Route not found: ${route}`,
|
|
95
|
-
data: null
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
const result = cached.function(params);
|
|
100
|
-
return {
|
|
101
|
-
success: true,
|
|
102
|
-
message: "Route executed successfully",
|
|
103
|
-
data: result
|
|
104
|
-
};
|
|
105
|
-
} catch (error) {
|
|
106
|
-
return {
|
|
107
|
-
success: false,
|
|
108
|
-
message: `Error executing route: ${error.message}`,
|
|
109
|
-
data: null,
|
|
110
|
-
error: error.message
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Load specific route for central service
|
|
116
|
-
async loadSpecificRoute(projectId, route) {
|
|
117
|
-
if (!this.isCentralService) {
|
|
118
|
-
throw new Error("Dynamic loading only available in central service mode");
|
|
119
|
-
}
|
|
120
|
-
try {
|
|
121
|
-
const db = await getDb();
|
|
122
|
-
const routeData = await db.collection("routes").findOne({
|
|
123
|
-
projectId,
|
|
124
|
-
route
|
|
125
|
-
});
|
|
126
|
-
if (routeData) {
|
|
127
|
-
this.compileAndCache(routeData);
|
|
128
|
-
console.log(`✅ Loaded route: ${route} for project ${projectId}`);
|
|
129
|
-
} else {
|
|
130
|
-
console.log(`❌ Route not found: ${route} for project ${projectId}`);
|
|
131
|
-
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
console.error(`❌ Failed to load route ${route} for project ${projectId}:`, error);
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Dynamic loading for central service
|
|
139
|
-
async loadProjectRoutes(projectId) {
|
|
140
|
-
if (!this.isCentralService) {
|
|
141
|
-
throw new Error("Dynamic loading only available in central service mode");
|
|
142
|
-
}
|
|
143
|
-
try {
|
|
144
|
-
const db = await getDb();
|
|
145
|
-
const routes = await db.collection("routes").find({
|
|
146
|
-
projectId
|
|
147
|
-
}).toArray();
|
|
148
|
-
routes.forEach(route => {
|
|
149
|
-
this.compileAndCache(route);
|
|
150
|
-
});
|
|
151
|
-
console.log(`✅ Loaded ${routes.length} routes for project ${projectId}`);
|
|
152
|
-
} catch (error) {
|
|
153
|
-
console.error(`❌ Failed to load routes for project ${projectId}:`, error);
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Security validation
|
|
159
|
-
validateCode(code) {
|
|
160
|
-
const dangerousPatterns = [/process\./, /require\(/, /eval\(/, /setTimeout\(/, /setInterval\(/, /global\./, /__dirname/, /__filename/];
|
|
161
|
-
return !dangerousPatterns.some(pattern => pattern.test(code));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Generate hash for change detection
|
|
165
|
-
generateHash(code) {
|
|
166
|
-
return crypto.createHash('md5').update(code).digest('hex');
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Update route (re-compile)
|
|
170
|
-
async updateRoute(projectId, route, newCode) {
|
|
171
|
-
const routeData = {
|
|
172
|
-
projectId,
|
|
173
|
-
route,
|
|
174
|
-
code: newCode
|
|
175
|
-
};
|
|
176
|
-
this.compileAndCache(routeData);
|
|
177
|
-
|
|
178
|
-
// Optionally save to database
|
|
179
|
-
try {
|
|
180
|
-
const db = await getDb();
|
|
181
|
-
await db.collection("routes").updateOne({
|
|
182
|
-
projectId,
|
|
183
|
-
route
|
|
184
|
-
}, {
|
|
185
|
-
$set: {
|
|
186
|
-
code: newCode,
|
|
187
|
-
updatedAt: new Date()
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
} catch (error) {
|
|
191
|
-
console.error(`❌ Failed to update route in database: ${route}`, error);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Get route statistics
|
|
196
|
-
getStats() {
|
|
197
|
-
return {
|
|
198
|
-
totalRoutes: this.compiledFunctions.size,
|
|
199
|
-
isInitialized: this.isInitialized,
|
|
200
|
-
isCentralService: this.isCentralService,
|
|
201
|
-
isEnabled: this.isEnabled,
|
|
202
|
-
cacheKeys: Array.from(this.compiledFunctions.keys())
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Clear cache (for testing or maintenance)
|
|
207
|
-
clearCache() {
|
|
208
|
-
this.compiledFunctions.clear();
|
|
209
|
-
console.log("🧹 Route cache cleared");
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Enable/Disable Plexx
|
|
213
|
-
enable() {
|
|
214
|
-
this.isEnabled = true;
|
|
215
|
-
console.log("✅ Plexx enabled");
|
|
216
|
-
}
|
|
217
|
-
disable() {
|
|
218
|
-
this.isEnabled = false;
|
|
219
|
-
console.log("🚫 Plexx disabled");
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Toggle Plexx
|
|
223
|
-
toggle() {
|
|
224
|
-
this.isEnabled = !this.isEnabled;
|
|
225
|
-
console.log(this.isEnabled ? "✅ Plexx enabled" : "🚫 Plexx disabled");
|
|
226
|
-
return this.isEnabled;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
module.exports = new PlexxManager();
|