@friggframework/devtools 2.0.0-next.29 → 2.0.0-next.30
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/frigg-cli/.eslintrc.js +141 -0
- package/frigg-cli/__tests__/jest.config.js +102 -0
- package/frigg-cli/__tests__/unit/commands/build.test.js +483 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +418 -0
- package/frigg-cli/__tests__/unit/commands/ui.test.js +592 -0
- package/frigg-cli/__tests__/utils/command-tester.js +170 -0
- package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
- package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
- package/frigg-cli/__tests__/utils/test-setup.js +286 -0
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +312 -0
- package/frigg-cli/generate-command/azure-generator.js +43 -0
- package/frigg-cli/generate-command/gcp-generator.js +47 -0
- package/frigg-cli/generate-command/index.js +332 -0
- package/frigg-cli/generate-command/terraform-generator.js +555 -0
- package/frigg-cli/index.js +19 -1
- package/frigg-cli/init-command/backend-first-handler.js +756 -0
- package/frigg-cli/init-command/index.js +93 -0
- package/frigg-cli/init-command/template-handler.js +143 -0
- package/frigg-cli/package.json +51 -0
- package/frigg-cli/test/init-command.test.js +180 -0
- package/frigg-cli/test/npm-registry.test.js +319 -0
- package/frigg-cli/ui-command/index.js +154 -0
- package/frigg-cli/utils/app-resolver.js +319 -0
- package/frigg-cli/utils/backend-path.js +25 -0
- package/frigg-cli/utils/npm-registry.js +167 -0
- package/frigg-cli/utils/process-manager.js +199 -0
- package/frigg-cli/utils/repo-detection.js +405 -0
- package/infrastructure/serverless-template.js +177 -292
- package/management-ui/.eslintrc.js +22 -0
- package/management-ui/README.md +203 -0
- package/management-ui/components.json +21 -0
- package/management-ui/docs/phase2-integration-guide.md +320 -0
- package/management-ui/{dist/index.html → index.html} +1 -2
- package/management-ui/package-lock.json +16517 -0
- package/management-ui/package.json +76 -0
- package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
- package/management-ui/postcss.config.js +6 -0
- package/management-ui/server/api/backend.js +256 -0
- package/management-ui/server/api/cli.js +315 -0
- package/management-ui/server/api/codegen.js +663 -0
- package/management-ui/server/api/connections.js +857 -0
- package/management-ui/server/api/discovery.js +185 -0
- package/management-ui/server/api/environment/index.js +1 -0
- package/management-ui/server/api/environment/router.js +378 -0
- package/management-ui/server/api/environment.js +328 -0
- package/management-ui/server/api/integrations.js +876 -0
- package/management-ui/server/api/logs.js +248 -0
- package/management-ui/server/api/monitoring.js +282 -0
- package/management-ui/server/api/open-ide.js +31 -0
- package/management-ui/server/api/project.js +1029 -0
- package/management-ui/server/api/users/sessions.js +371 -0
- package/management-ui/server/api/users/simulation.js +254 -0
- package/management-ui/server/api/users.js +362 -0
- package/management-ui/server/api-contract.md +275 -0
- package/management-ui/server/index.js +873 -0
- package/management-ui/server/middleware/errorHandler.js +93 -0
- package/management-ui/server/middleware/security.js +32 -0
- package/management-ui/server/processManager.js +296 -0
- package/management-ui/server/server.js +346 -0
- package/management-ui/server/services/aws-monitor.js +413 -0
- package/management-ui/server/services/npm-registry.js +347 -0
- package/management-ui/server/services/template-engine.js +538 -0
- package/management-ui/server/utils/cliIntegration.js +220 -0
- package/management-ui/server/utils/environment/auditLogger.js +471 -0
- package/management-ui/server/utils/environment/awsParameterStore.js +264 -0
- package/management-ui/server/utils/environment/encryption.js +278 -0
- package/management-ui/server/utils/environment/envFileManager.js +286 -0
- package/management-ui/server/utils/import-commonjs.js +28 -0
- package/management-ui/server/utils/response.js +83 -0
- package/management-ui/server/websocket/handler.js +325 -0
- package/management-ui/src/App.jsx +109 -0
- package/management-ui/src/components/AppRouter.jsx +65 -0
- package/management-ui/src/components/Button.jsx +70 -0
- package/management-ui/src/components/Card.jsx +97 -0
- package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
- package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
- package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
- package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
- package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
- package/management-ui/src/components/ErrorBoundary.jsx +73 -0
- package/management-ui/src/components/IntegrationCard.jsx +481 -0
- package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
- package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
- package/management-ui/src/components/IntegrationStatus.jsx +336 -0
- package/management-ui/src/components/Layout.jsx +716 -0
- package/management-ui/src/components/LoadingSpinner.jsx +113 -0
- package/management-ui/src/components/RepositoryPicker.jsx +248 -0
- package/management-ui/src/components/SessionMonitor.jsx +350 -0
- package/management-ui/src/components/StatusBadge.jsx +208 -0
- package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
- package/management-ui/src/components/UserSimulation.jsx +327 -0
- package/management-ui/src/components/Welcome.jsx +434 -0
- package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
- package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
- package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
- package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
- package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
- package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
- package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
- package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
- package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
- package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
- package/management-ui/src/components/codegen/index.js +10 -0
- package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
- package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
- package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
- package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
- package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
- package/management-ui/src/components/connections/index.js +5 -0
- package/management-ui/src/components/index.js +21 -0
- package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
- package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
- package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
- package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
- package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
- package/management-ui/src/components/monitoring/index.js +6 -0
- package/management-ui/src/components/monitoring/monitoring.css +218 -0
- package/management-ui/src/components/theme-provider.jsx +52 -0
- package/management-ui/src/components/theme-toggle.jsx +39 -0
- package/management-ui/src/components/ui/badge.tsx +36 -0
- package/management-ui/src/components/ui/button.test.jsx +56 -0
- package/management-ui/src/components/ui/button.tsx +57 -0
- package/management-ui/src/components/ui/card.tsx +76 -0
- package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
- package/management-ui/src/components/ui/select.tsx +157 -0
- package/management-ui/src/components/ui/skeleton.jsx +15 -0
- package/management-ui/src/hooks/useFrigg.jsx +601 -0
- package/management-ui/src/hooks/useSocket.jsx +58 -0
- package/management-ui/src/index.css +193 -0
- package/management-ui/src/lib/utils.ts +6 -0
- package/management-ui/src/main.jsx +10 -0
- package/management-ui/src/pages/CodeGeneration.jsx +14 -0
- package/management-ui/src/pages/Connections.jsx +252 -0
- package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
- package/management-ui/src/pages/Dashboard.jsx +311 -0
- package/management-ui/src/pages/Environment.jsx +314 -0
- package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
- package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
- package/management-ui/src/pages/IntegrationTest.jsx +742 -0
- package/management-ui/src/pages/Integrations.jsx +253 -0
- package/management-ui/src/pages/Monitoring.jsx +17 -0
- package/management-ui/src/pages/Simulation.jsx +155 -0
- package/management-ui/src/pages/Users.jsx +492 -0
- package/management-ui/src/services/api.js +41 -0
- package/management-ui/src/services/apiModuleService.js +193 -0
- package/management-ui/src/services/websocket-handlers.js +120 -0
- package/management-ui/src/test/api/project.test.js +273 -0
- package/management-ui/src/test/components/Welcome.test.jsx +378 -0
- package/management-ui/src/test/mocks/server.js +178 -0
- package/management-ui/src/test/setup.js +61 -0
- package/management-ui/src/test/utils/test-utils.jsx +134 -0
- package/management-ui/src/utils/repository.js +98 -0
- package/management-ui/src/utils/repository.test.js +118 -0
- package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
- package/management-ui/tailwind.config.js +63 -0
- package/management-ui/tsconfig.json +37 -0
- package/management-ui/tsconfig.node.json +10 -0
- package/management-ui/vite.config.js +26 -0
- package/management-ui/vitest.config.js +38 -0
- package/package.json +5 -5
- package/management-ui/dist/assets/index-BA21WgFa.js +0 -1221
- package/management-ui/dist/assets/index-CbM64Oba.js +0 -1221
- package/management-ui/dist/assets/index-CkvseXTC.css +0 -1
- /package/management-ui/{dist/assets/FriggLogo-B7Xx8ZW1.svg → src/assets/FriggLogo.svg} +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import express from 'express'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import fs from 'fs-extra'
|
|
4
|
+
import crypto from 'crypto'
|
|
5
|
+
import { createStandardResponse, createErrorResponse, ERROR_CODES, asyncHandler } from '../utils/response.js'
|
|
6
|
+
import { wsHandler } from '../websocket/handler.js'
|
|
7
|
+
import simulationRouter from './users/simulation.js'
|
|
8
|
+
import sessionsRouter from './users/sessions.js'
|
|
9
|
+
|
|
10
|
+
const router = express.Router();
|
|
11
|
+
|
|
12
|
+
// Mount sub-routes
|
|
13
|
+
router.use('/simulation', simulationRouter);
|
|
14
|
+
router.use('/sessions', sessionsRouter);
|
|
15
|
+
|
|
16
|
+
// Helper to get users data file path
|
|
17
|
+
async function getUsersFilePath() {
|
|
18
|
+
const dataDir = path.join(process.cwd(), '../../../backend/data');
|
|
19
|
+
await fs.ensureDir(dataDir);
|
|
20
|
+
return path.join(dataDir, 'dummy-users.json');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Helper to load users
|
|
24
|
+
async function loadUsers() {
|
|
25
|
+
try {
|
|
26
|
+
const filePath = await getUsersFilePath();
|
|
27
|
+
if (await fs.pathExists(filePath)) {
|
|
28
|
+
return await fs.readJson(filePath);
|
|
29
|
+
}
|
|
30
|
+
return { users: [] };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error loading users:', error);
|
|
33
|
+
return { users: [] };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Helper to save users
|
|
38
|
+
async function saveUsers(data) {
|
|
39
|
+
const filePath = await getUsersFilePath();
|
|
40
|
+
await fs.writeJson(filePath, data, { spaces: 2 });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Helper to generate dummy user data
|
|
44
|
+
function generateDummyUser(data = {}) {
|
|
45
|
+
const id = data.id || crypto.randomBytes(16).toString('hex');
|
|
46
|
+
const firstName = data.firstName || 'Test';
|
|
47
|
+
const lastName = data.lastName || 'User';
|
|
48
|
+
const email = data.email || `user_${Date.now()}@example.com`;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
id,
|
|
52
|
+
appUserId: data.appUserId || `app_user_${crypto.randomBytes(8).toString('hex')}`,
|
|
53
|
+
appOrgId: data.appOrgId || `app_org_${crypto.randomBytes(8).toString('hex')}`,
|
|
54
|
+
firstName,
|
|
55
|
+
lastName,
|
|
56
|
+
email,
|
|
57
|
+
username: data.username || email.split('@')[0],
|
|
58
|
+
avatar: data.avatar || `https://ui-avatars.com/api/?name=${firstName}+${lastName}`,
|
|
59
|
+
role: data.role || 'user',
|
|
60
|
+
status: data.status || 'active',
|
|
61
|
+
createdAt: data.createdAt || new Date().toISOString(),
|
|
62
|
+
updatedAt: new Date().toISOString(),
|
|
63
|
+
metadata: data.metadata || {},
|
|
64
|
+
connections: data.connections || []
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Get all users
|
|
69
|
+
router.get('/', async (req, res) => {
|
|
70
|
+
try {
|
|
71
|
+
const { page = 1, limit = 10, search, role, status } = req.query;
|
|
72
|
+
const data = await loadUsers();
|
|
73
|
+
let users = data.users || [];
|
|
74
|
+
|
|
75
|
+
// Apply filters
|
|
76
|
+
if (search) {
|
|
77
|
+
const searchLower = search.toLowerCase();
|
|
78
|
+
users = users.filter(user =>
|
|
79
|
+
user.email.toLowerCase().includes(searchLower) ||
|
|
80
|
+
user.firstName.toLowerCase().includes(searchLower) ||
|
|
81
|
+
user.lastName.toLowerCase().includes(searchLower) ||
|
|
82
|
+
user.username.toLowerCase().includes(searchLower)
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (role) {
|
|
87
|
+
users = users.filter(user => user.role === role);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (status) {
|
|
91
|
+
users = users.filter(user => user.status === status);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Pagination
|
|
95
|
+
const startIndex = (page - 1) * limit;
|
|
96
|
+
const endIndex = startIndex + parseInt(limit);
|
|
97
|
+
const paginatedUsers = users.slice(startIndex, endIndex);
|
|
98
|
+
|
|
99
|
+
res.json({
|
|
100
|
+
users: paginatedUsers,
|
|
101
|
+
total: users.length,
|
|
102
|
+
page: parseInt(page),
|
|
103
|
+
limit: parseInt(limit),
|
|
104
|
+
totalPages: Math.ceil(users.length / limit)
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
res.status(500).json({
|
|
108
|
+
error: error.message,
|
|
109
|
+
details: 'Failed to fetch users'
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Get single user
|
|
115
|
+
router.get('/:id', async (req, res) => {
|
|
116
|
+
const { id } = req.params;
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
const data = await loadUsers();
|
|
120
|
+
const user = data.users.find(u => u.id === id);
|
|
121
|
+
|
|
122
|
+
if (!user) {
|
|
123
|
+
return res.status(404).json({
|
|
124
|
+
error: 'User not found'
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
res.json(user);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
res.status(500).json({
|
|
131
|
+
error: error.message,
|
|
132
|
+
details: 'Failed to fetch user'
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Create new user
|
|
138
|
+
router.post('/', async (req, res) => {
|
|
139
|
+
try {
|
|
140
|
+
const userData = req.body;
|
|
141
|
+
const newUser = generateDummyUser(userData);
|
|
142
|
+
|
|
143
|
+
const data = await loadUsers();
|
|
144
|
+
|
|
145
|
+
// Check if email already exists
|
|
146
|
+
if (data.users.some(u => u.email === newUser.email)) {
|
|
147
|
+
return res.status(400).json({
|
|
148
|
+
error: 'Email already exists'
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
data.users.push(newUser);
|
|
153
|
+
await saveUsers(data);
|
|
154
|
+
|
|
155
|
+
// Broadcast user creation
|
|
156
|
+
wsHandler.broadcast('user-update', {
|
|
157
|
+
action: 'created',
|
|
158
|
+
user: newUser,
|
|
159
|
+
timestamp: new Date().toISOString()
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
res.status(201).json(newUser);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
res.status(500).json({
|
|
165
|
+
error: error.message,
|
|
166
|
+
details: 'Failed to create user'
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Update user
|
|
172
|
+
router.put('/:id', async (req, res) => {
|
|
173
|
+
const { id } = req.params;
|
|
174
|
+
const updates = req.body;
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const data = await loadUsers();
|
|
178
|
+
const userIndex = data.users.findIndex(u => u.id === id);
|
|
179
|
+
|
|
180
|
+
if (userIndex === -1) {
|
|
181
|
+
return res.status(404).json({
|
|
182
|
+
error: 'User not found'
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Update user
|
|
187
|
+
const updatedUser = {
|
|
188
|
+
...data.users[userIndex],
|
|
189
|
+
...updates,
|
|
190
|
+
id, // Prevent ID from being changed
|
|
191
|
+
updatedAt: new Date().toISOString()
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
data.users[userIndex] = updatedUser;
|
|
195
|
+
await saveUsers(data);
|
|
196
|
+
|
|
197
|
+
// Broadcast user update
|
|
198
|
+
wsHandler.broadcast('user-update', {
|
|
199
|
+
action: 'updated',
|
|
200
|
+
user: updatedUser,
|
|
201
|
+
timestamp: new Date().toISOString()
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
res.json(updatedUser);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
res.status(500).json({
|
|
207
|
+
error: error.message,
|
|
208
|
+
details: 'Failed to update user'
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Delete user
|
|
214
|
+
router.delete('/:id', async (req, res) => {
|
|
215
|
+
const { id } = req.params;
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const data = await loadUsers();
|
|
219
|
+
const userIndex = data.users.findIndex(u => u.id === id);
|
|
220
|
+
|
|
221
|
+
if (userIndex === -1) {
|
|
222
|
+
return res.status(404).json({
|
|
223
|
+
error: 'User not found'
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const deletedUser = data.users[userIndex];
|
|
228
|
+
data.users.splice(userIndex, 1);
|
|
229
|
+
await saveUsers(data);
|
|
230
|
+
|
|
231
|
+
// Broadcast user deletion
|
|
232
|
+
wsHandler.broadcast('user-update', {
|
|
233
|
+
action: 'deleted',
|
|
234
|
+
userId: id,
|
|
235
|
+
timestamp: new Date().toISOString()
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
res.json({
|
|
239
|
+
status: 'success',
|
|
240
|
+
message: 'User deleted',
|
|
241
|
+
user: deletedUser
|
|
242
|
+
});
|
|
243
|
+
} catch (error) {
|
|
244
|
+
res.status(500).json({
|
|
245
|
+
error: error.message,
|
|
246
|
+
details: 'Failed to delete user'
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Bulk create users
|
|
252
|
+
router.post('/bulk', async (req, res) => {
|
|
253
|
+
const { count = 10 } = req.body;
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
const data = await loadUsers();
|
|
257
|
+
const newUsers = [];
|
|
258
|
+
|
|
259
|
+
for (let i = 0; i < count; i++) {
|
|
260
|
+
const user = generateDummyUser({
|
|
261
|
+
firstName: `Test${i + 1}`,
|
|
262
|
+
lastName: `User${i + 1}`,
|
|
263
|
+
email: `test.user${i + 1}_${Date.now()}@example.com`,
|
|
264
|
+
role: i % 3 === 0 ? 'admin' : 'user',
|
|
265
|
+
status: i % 5 === 0 ? 'inactive' : 'active',
|
|
266
|
+
appUserId: `app_user_test_${i + 1}`,
|
|
267
|
+
appOrgId: `app_org_${Math.floor(i / 5) + 1}` // Group users into orgs
|
|
268
|
+
});
|
|
269
|
+
newUsers.push(user);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
data.users.push(...newUsers);
|
|
273
|
+
await saveUsers(data);
|
|
274
|
+
|
|
275
|
+
// Broadcast bulk creation
|
|
276
|
+
wsHandler.broadcast('user-update', {
|
|
277
|
+
action: 'bulk-created',
|
|
278
|
+
count: newUsers.length,
|
|
279
|
+
timestamp: new Date().toISOString()
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
res.json({
|
|
283
|
+
status: 'success',
|
|
284
|
+
message: `Created ${count} dummy users`,
|
|
285
|
+
users: newUsers
|
|
286
|
+
});
|
|
287
|
+
} catch (error) {
|
|
288
|
+
res.status(500).json({
|
|
289
|
+
error: error.message,
|
|
290
|
+
details: 'Failed to create bulk users'
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Delete all users
|
|
296
|
+
router.delete('/', async (req, res) => {
|
|
297
|
+
try {
|
|
298
|
+
await saveUsers({ users: [] });
|
|
299
|
+
|
|
300
|
+
// Broadcast deletion
|
|
301
|
+
wsHandler.broadcast('user-update', {
|
|
302
|
+
action: 'all-deleted',
|
|
303
|
+
timestamp: new Date().toISOString()
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
res.json({
|
|
307
|
+
status: 'success',
|
|
308
|
+
message: 'All users deleted'
|
|
309
|
+
});
|
|
310
|
+
} catch (error) {
|
|
311
|
+
res.status(500).json({
|
|
312
|
+
error: error.message,
|
|
313
|
+
details: 'Failed to delete all users'
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// User statistics
|
|
319
|
+
router.get('/stats/summary', async (req, res) => {
|
|
320
|
+
try {
|
|
321
|
+
const data = await loadUsers();
|
|
322
|
+
const users = data.users || [];
|
|
323
|
+
|
|
324
|
+
const stats = {
|
|
325
|
+
total: users.length,
|
|
326
|
+
byRole: {},
|
|
327
|
+
byStatus: {},
|
|
328
|
+
recentlyCreated: 0,
|
|
329
|
+
recentlyUpdated: 0
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const now = new Date();
|
|
333
|
+
const dayAgo = new Date(now - 24 * 60 * 60 * 1000);
|
|
334
|
+
|
|
335
|
+
users.forEach(user => {
|
|
336
|
+
// Count by role
|
|
337
|
+
stats.byRole[user.role] = (stats.byRole[user.role] || 0) + 1;
|
|
338
|
+
|
|
339
|
+
// Count by status
|
|
340
|
+
stats.byStatus[user.status] = (stats.byStatus[user.status] || 0) + 1;
|
|
341
|
+
|
|
342
|
+
// Count recently created
|
|
343
|
+
if (new Date(user.createdAt) > dayAgo) {
|
|
344
|
+
stats.recentlyCreated++;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Count recently updated
|
|
348
|
+
if (new Date(user.updatedAt) > dayAgo) {
|
|
349
|
+
stats.recentlyUpdated++;
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
res.json(stats);
|
|
354
|
+
} catch (error) {
|
|
355
|
+
res.status(500).json({
|
|
356
|
+
error: error.message,
|
|
357
|
+
details: 'Failed to get user statistics'
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
export default router
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Frigg Management UI API Contract
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This document defines the API contract for CLI-GUI communication in the Frigg Management UI, implementing Phase 1 requirements from RFC 0001.
|
|
5
|
+
|
|
6
|
+
## Base Configuration
|
|
7
|
+
- **Base URL**: `http://localhost:3001/api`
|
|
8
|
+
- **WebSocket**: `ws://localhost:3001`
|
|
9
|
+
- **Content-Type**: `application/json`
|
|
10
|
+
- **Protocol**: REST API + WebSocket for real-time updates
|
|
11
|
+
|
|
12
|
+
## Standard Response Format
|
|
13
|
+
|
|
14
|
+
### Success Response
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"status": "success",
|
|
18
|
+
"data": any,
|
|
19
|
+
"message": string,
|
|
20
|
+
"timestamp": ISO8601
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Error Response
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"status": "error",
|
|
28
|
+
"error": {
|
|
29
|
+
"code": string,
|
|
30
|
+
"message": string,
|
|
31
|
+
"details": any
|
|
32
|
+
},
|
|
33
|
+
"timestamp": ISO8601
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API Endpoints
|
|
38
|
+
|
|
39
|
+
### 1. Project Management
|
|
40
|
+
#### GET /api/project/status
|
|
41
|
+
Get current project status and configuration.
|
|
42
|
+
|
|
43
|
+
**Response:**
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"status": "success",
|
|
47
|
+
"data": {
|
|
48
|
+
"name": "my-frigg-app",
|
|
49
|
+
"version": "1.0.0",
|
|
50
|
+
"friggVersion": "2.5.0",
|
|
51
|
+
"status": "running|stopped|starting|stopping",
|
|
52
|
+
"pid": number|null,
|
|
53
|
+
"uptime": number,
|
|
54
|
+
"port": number,
|
|
55
|
+
"environment": "development|staging|production",
|
|
56
|
+
"lastStarted": ISO8601|null
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### POST /api/project/start
|
|
62
|
+
Start the Frigg project.
|
|
63
|
+
|
|
64
|
+
**Request:**
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"stage": "dev|staging|production",
|
|
68
|
+
"verbose": boolean,
|
|
69
|
+
"port": number
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### POST /api/project/stop
|
|
74
|
+
Stop the Frigg project.
|
|
75
|
+
|
|
76
|
+
#### POST /api/project/restart
|
|
77
|
+
Restart the Frigg project with optional new configuration.
|
|
78
|
+
|
|
79
|
+
### 2. Integration Management
|
|
80
|
+
#### GET /api/integrations
|
|
81
|
+
List all available and installed integrations.
|
|
82
|
+
|
|
83
|
+
**Response:**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"status": "success",
|
|
87
|
+
"data": {
|
|
88
|
+
"installed": [
|
|
89
|
+
{
|
|
90
|
+
"id": string,
|
|
91
|
+
"name": string,
|
|
92
|
+
"displayName": string,
|
|
93
|
+
"version": string,
|
|
94
|
+
"description": string,
|
|
95
|
+
"status": "active|inactive|error",
|
|
96
|
+
"installedAt": ISO8601,
|
|
97
|
+
"configRequired": boolean
|
|
98
|
+
}
|
|
99
|
+
],
|
|
100
|
+
"available": [
|
|
101
|
+
{
|
|
102
|
+
"name": string,
|
|
103
|
+
"displayName": string,
|
|
104
|
+
"description": string,
|
|
105
|
+
"version": string,
|
|
106
|
+
"category": string,
|
|
107
|
+
"documentation": string
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### POST /api/integrations/install
|
|
115
|
+
Install a new integration.
|
|
116
|
+
|
|
117
|
+
**Request:**
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"name": string,
|
|
121
|
+
"version": string,
|
|
122
|
+
"autoConfig": boolean
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### DELETE /api/integrations/:id
|
|
127
|
+
Uninstall an integration.
|
|
128
|
+
|
|
129
|
+
#### PUT /api/integrations/:id/configure
|
|
130
|
+
Configure an integration.
|
|
131
|
+
|
|
132
|
+
**Request:**
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"config": Record<string, any>
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 3. Environment Management
|
|
140
|
+
#### GET /api/environment
|
|
141
|
+
Get environment variables.
|
|
142
|
+
|
|
143
|
+
**Response:**
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"status": "success",
|
|
147
|
+
"data": {
|
|
148
|
+
"variables": Record<string, string>,
|
|
149
|
+
"stage": "development|staging|production",
|
|
150
|
+
"source": "file|aws-parameter-store"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### PUT /api/environment
|
|
156
|
+
Update environment variables.
|
|
157
|
+
|
|
158
|
+
**Request:**
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"variables": Record<string, string>,
|
|
162
|
+
"stage": string,
|
|
163
|
+
"writeToFile": boolean
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 4. User Management (Test/Development)
|
|
168
|
+
#### GET /api/users
|
|
169
|
+
Get test users for development.
|
|
170
|
+
|
|
171
|
+
#### POST /api/users
|
|
172
|
+
Create a test user.
|
|
173
|
+
|
|
174
|
+
#### DELETE /api/users/:id
|
|
175
|
+
Delete a test user.
|
|
176
|
+
|
|
177
|
+
### 5. Connection Management
|
|
178
|
+
#### GET /api/connections
|
|
179
|
+
Get active connections and entities.
|
|
180
|
+
|
|
181
|
+
#### POST /api/connections/:integration/test
|
|
182
|
+
Test a connection for an integration.
|
|
183
|
+
|
|
184
|
+
#### GET /api/connections/:integration/entities
|
|
185
|
+
Get entities for a specific integration.
|
|
186
|
+
|
|
187
|
+
### 6. CLI Interface
|
|
188
|
+
#### POST /api/cli/execute
|
|
189
|
+
Execute CLI commands from the GUI.
|
|
190
|
+
|
|
191
|
+
**Request:**
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"command": string,
|
|
195
|
+
"args": string[],
|
|
196
|
+
"options": Record<string, any>
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
#### GET /api/cli/commands
|
|
201
|
+
Get available CLI commands.
|
|
202
|
+
|
|
203
|
+
### 7. Logs and Monitoring
|
|
204
|
+
#### GET /api/logs
|
|
205
|
+
Get application logs.
|
|
206
|
+
|
|
207
|
+
**Query Parameters:**
|
|
208
|
+
- `limit`: number (default: 100)
|
|
209
|
+
- `level`: "error|warn|info|debug"
|
|
210
|
+
- `since`: ISO8601
|
|
211
|
+
- `component`: string
|
|
212
|
+
|
|
213
|
+
#### DELETE /api/logs
|
|
214
|
+
Clear logs.
|
|
215
|
+
|
|
216
|
+
## WebSocket Events
|
|
217
|
+
|
|
218
|
+
### Connection Management
|
|
219
|
+
- `connection` - Client connected
|
|
220
|
+
- `disconnect` - Client disconnected
|
|
221
|
+
- `error` - Connection error
|
|
222
|
+
|
|
223
|
+
### Project Events
|
|
224
|
+
- `project:status` - Project status changed
|
|
225
|
+
- `project:logs` - New log entries
|
|
226
|
+
- `project:error` - Project error occurred
|
|
227
|
+
|
|
228
|
+
### Integration Events
|
|
229
|
+
- `integrations:update` - Integration list changed
|
|
230
|
+
- `integrations:install` - Integration installed
|
|
231
|
+
- `integrations:uninstall` - Integration removed
|
|
232
|
+
- `integrations:configure` - Integration configured
|
|
233
|
+
|
|
234
|
+
### Environment Events
|
|
235
|
+
- `environment:update` - Environment variables changed
|
|
236
|
+
- `environment:sync` - Environment synced with remote
|
|
237
|
+
|
|
238
|
+
### CLI Events
|
|
239
|
+
- `cli:output` - CLI command output
|
|
240
|
+
- `cli:complete` - CLI command completed
|
|
241
|
+
- `cli:error` - CLI command error
|
|
242
|
+
|
|
243
|
+
## Error Codes
|
|
244
|
+
|
|
245
|
+
### General Errors
|
|
246
|
+
- `INVALID_REQUEST` - Invalid request format
|
|
247
|
+
- `UNAUTHORIZED` - Authentication required
|
|
248
|
+
- `FORBIDDEN` - Insufficient permissions
|
|
249
|
+
- `NOT_FOUND` - Resource not found
|
|
250
|
+
- `INTERNAL_ERROR` - Server error
|
|
251
|
+
|
|
252
|
+
### Project Errors
|
|
253
|
+
- `PROJECT_NOT_FOUND` - No Frigg project found
|
|
254
|
+
- `PROJECT_ALREADY_RUNNING` - Project is already running
|
|
255
|
+
- `PROJECT_NOT_RUNNING` - Project is not running
|
|
256
|
+
- `PROJECT_START_FAILED` - Failed to start project
|
|
257
|
+
- `PROJECT_STOP_FAILED` - Failed to stop project
|
|
258
|
+
|
|
259
|
+
### Integration Errors
|
|
260
|
+
- `INTEGRATION_NOT_FOUND` - Integration not found
|
|
261
|
+
- `INTEGRATION_ALREADY_INSTALLED` - Integration already installed
|
|
262
|
+
- `INTEGRATION_INSTALL_FAILED` - Installation failed
|
|
263
|
+
- `INTEGRATION_CONFIG_INVALID` - Invalid configuration
|
|
264
|
+
|
|
265
|
+
### Environment Errors
|
|
266
|
+
- `ENV_READ_FAILED` - Failed to read environment
|
|
267
|
+
- `ENV_WRITE_FAILED` - Failed to write environment
|
|
268
|
+
- `ENV_SYNC_FAILED` - Failed to sync with remote
|
|
269
|
+
|
|
270
|
+
## Security Considerations
|
|
271
|
+
- Local development only (no external network calls)
|
|
272
|
+
- Environment variables properly masked in responses
|
|
273
|
+
- File system access limited to project directory
|
|
274
|
+
- Process management restricted to Frigg processes
|
|
275
|
+
- WebSocket connections authenticated via session
|