@friggframework/devtools 2.0.0--canary.398.dd443c7.0 → 2.0.0--canary.402.d2f4ae6.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/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,876 @@
|
|
|
1
|
+
import express from 'express'
|
|
2
|
+
import { exec } from 'child_process'
|
|
3
|
+
import { promisify } from 'util'
|
|
4
|
+
import path from 'path'
|
|
5
|
+
import fs from 'fs-extra'
|
|
6
|
+
<<<<<<< HEAD
|
|
7
|
+
<<<<<<< HEAD
|
|
8
|
+
import fetch from 'node-fetch'
|
|
9
|
+
=======
|
|
10
|
+
<<<<<<< HEAD
|
|
11
|
+
<<<<<<< HEAD
|
|
12
|
+
import fetch from 'node-fetch'
|
|
13
|
+
=======
|
|
14
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
15
|
+
=======
|
|
16
|
+
import fetch from 'node-fetch'
|
|
17
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
18
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
19
|
+
=======
|
|
20
|
+
import fetch from 'node-fetch'
|
|
21
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
22
|
+
import { createStandardResponse, createErrorResponse, ERROR_CODES, asyncHandler } from '../utils/response.js'
|
|
23
|
+
import { importCommonJS } from '../utils/import-commonjs.js'
|
|
24
|
+
import { wsHandler } from '../websocket/handler.js'
|
|
25
|
+
|
|
26
|
+
const router = express.Router();
|
|
27
|
+
const execAsync = promisify(exec);
|
|
28
|
+
|
|
29
|
+
<<<<<<< HEAD
|
|
30
|
+
<<<<<<< HEAD
|
|
31
|
+
=======
|
|
32
|
+
<<<<<<< HEAD
|
|
33
|
+
<<<<<<< HEAD
|
|
34
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
35
|
+
=======
|
|
36
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
37
|
+
// Helper to get available integrations from NPM
|
|
38
|
+
async function getAvailableIntegrations() {
|
|
39
|
+
try {
|
|
40
|
+
// Search NPM registry for @friggframework/api-module-* packages
|
|
41
|
+
const searchUrl = 'https://registry.npmjs.org/-/v1/search?text=@friggframework%20api-module&size=100';
|
|
42
|
+
<<<<<<< HEAD
|
|
43
|
+
<<<<<<< HEAD
|
|
44
|
+
=======
|
|
45
|
+
|
|
46
|
+
const response = await fetch(searchUrl);
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`NPM search failed: ${response.statusText}`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const data = await response.json();
|
|
52
|
+
|
|
53
|
+
// Filter and format integration packages
|
|
54
|
+
const integrations = data.objects
|
|
55
|
+
.filter(pkg => pkg.package.name.includes('@friggframework/api-module-'))
|
|
56
|
+
.map(pkg => ({
|
|
57
|
+
name: pkg.package.name,
|
|
58
|
+
version: pkg.package.version,
|
|
59
|
+
description: pkg.package.description || 'No description available',
|
|
60
|
+
category: detectCategory(pkg.package.name, pkg.package.description || '', pkg.package.keywords || []),
|
|
61
|
+
installed: false,
|
|
62
|
+
tags: pkg.package.keywords || [],
|
|
63
|
+
npmUrl: `https://www.npmjs.com/package/${pkg.package.name}`
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
console.log(`Found ${integrations.length} available integrations from NPM`);
|
|
67
|
+
return integrations;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.error('Error fetching integrations from NPM:', error);
|
|
70
|
+
// Fallback to basic list if NPM search fails
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
name: '@friggframework/api-module-hubspot',
|
|
74
|
+
version: 'latest',
|
|
75
|
+
description: 'HubSpot CRM integration for Frigg',
|
|
76
|
+
category: 'CRM',
|
|
77
|
+
installed: false
|
|
78
|
+
}
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Helper to detect integration category
|
|
84
|
+
function detectCategory(name, description, keywords) {
|
|
85
|
+
const text = `${name} ${description} ${keywords.join(' ')}`.toLowerCase();
|
|
86
|
+
|
|
87
|
+
const categoryPatterns = {
|
|
88
|
+
'CRM': ['crm', 'customer', 'salesforce', 'hubspot', 'pipedrive'],
|
|
89
|
+
'Communication': ['email', 'sms', 'chat', 'slack', 'discord', 'teams'],
|
|
90
|
+
'E-commerce': ['ecommerce', 'shop', 'store', 'payment', 'stripe', 'paypal'],
|
|
91
|
+
'Marketing': ['marketing', 'campaign', 'mailchimp', 'activecampaign'],
|
|
92
|
+
'Productivity': ['task', 'project', 'asana', 'trello', 'notion', 'jira'],
|
|
93
|
+
'Analytics': ['analytics', 'tracking', 'google', 'mixpanel', 'segment'],
|
|
94
|
+
'Support': ['support', 'helpdesk', 'ticket', 'zendesk', 'intercom'],
|
|
95
|
+
'Finance': ['accounting', 'invoice', 'quickbooks', 'xero', 'billing'],
|
|
96
|
+
'Developer Tools': ['github', 'gitlab', 'bitbucket', 'api', 'webhook'],
|
|
97
|
+
'Social Media': ['social', 'facebook', 'twitter', 'instagram', 'linkedin']
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
for (const [category, patterns] of Object.entries(categoryPatterns)) {
|
|
101
|
+
for (const pattern of patterns) {
|
|
102
|
+
if (text.includes(pattern)) {
|
|
103
|
+
return category;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return 'Other';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Helper to get actual integrations from backend.js appDefinition
|
|
112
|
+
async function getInstalledIntegrations() {
|
|
113
|
+
try {
|
|
114
|
+
// Try multiple possible backend locations
|
|
115
|
+
const possiblePaths = [
|
|
116
|
+
path.join(process.cwd(), '../../../backend'),
|
|
117
|
+
path.join(process.cwd(), '../../backend'),
|
|
118
|
+
path.join(process.cwd(), '../backend'),
|
|
119
|
+
path.join(process.cwd(), 'backend'),
|
|
120
|
+
// Also check template backend
|
|
121
|
+
path.join(process.cwd(), '../frigg-cli/templates/backend')
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
for (const backendPath of possiblePaths) {
|
|
125
|
+
const backendJsPath = path.join(backendPath, 'backend.js');
|
|
126
|
+
const indexJsPath = path.join(backendPath, 'index.js');
|
|
127
|
+
|
|
128
|
+
// Try both backend.js and index.js
|
|
129
|
+
const targetFile = await fs.pathExists(backendJsPath) ? backendJsPath :
|
|
130
|
+
await fs.pathExists(indexJsPath) ? indexJsPath : null;
|
|
131
|
+
|
|
132
|
+
if (targetFile) {
|
|
133
|
+
console.log(`Found backend file at: ${targetFile}`);
|
|
134
|
+
|
|
135
|
+
try {
|
|
136
|
+
// Dynamically import the backend file to get the actual appDefinition
|
|
137
|
+
const backendModule = require(targetFile);
|
|
138
|
+
|
|
139
|
+
// Extract appDefinition - could be default export, named export, or variable
|
|
140
|
+
const appDefinition = backendModule.default?.appDefinition ||
|
|
141
|
+
backendModule.appDefinition ||
|
|
142
|
+
backendModule.default ||
|
|
143
|
+
backendModule;
|
|
144
|
+
|
|
145
|
+
if (appDefinition && appDefinition.integrations && Array.isArray(appDefinition.integrations)) {
|
|
146
|
+
console.log(`Found ${appDefinition.integrations.length} integrations in appDefinition`);
|
|
147
|
+
|
|
148
|
+
const integrations = appDefinition.integrations.map((IntegrationClass, index) => {
|
|
149
|
+
try {
|
|
150
|
+
// Get integration metadata from static properties
|
|
151
|
+
const config = IntegrationClass.Config || {};
|
|
152
|
+
const options = IntegrationClass.Options || {};
|
|
153
|
+
const modules = IntegrationClass.modules || {};
|
|
154
|
+
const display = options.display || {};
|
|
155
|
+
|
|
156
|
+
// Extract service name from class name
|
|
157
|
+
const className = IntegrationClass.name || `Integration${index}`;
|
|
158
|
+
const serviceName = className.replace(/Integration$/, '');
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
name: config.name || serviceName.toLowerCase(),
|
|
162
|
+
displayName: display.name || serviceName,
|
|
163
|
+
description: display.description || `${serviceName} integration`,
|
|
164
|
+
category: display.category || detectCategory(serviceName.toLowerCase(), display.description || '', []),
|
|
165
|
+
version: config.version || '1.0.0',
|
|
166
|
+
installed: true,
|
|
167
|
+
status: 'active',
|
|
168
|
+
type: 'integration',
|
|
169
|
+
className: className,
|
|
170
|
+
|
|
171
|
+
// Integration configuration details
|
|
172
|
+
events: config.events || [],
|
|
173
|
+
supportedVersions: config.supportedVersions || [],
|
|
174
|
+
hasUserConfig: options.hasUserConfig || false,
|
|
175
|
+
|
|
176
|
+
// Display properties
|
|
177
|
+
icon: display.icon,
|
|
178
|
+
detailsUrl: display.detailsUrl,
|
|
179
|
+
|
|
180
|
+
// API Modules information
|
|
181
|
+
apiModules: Object.keys(modules).map(key => ({
|
|
182
|
+
name: key,
|
|
183
|
+
module: modules[key]?.name || key,
|
|
184
|
+
description: `API module for ${key}`
|
|
185
|
+
})),
|
|
186
|
+
|
|
187
|
+
// Constructor details
|
|
188
|
+
constructor: {
|
|
189
|
+
name: className,
|
|
190
|
+
hasConfig: !!config,
|
|
191
|
+
hasOptions: !!options,
|
|
192
|
+
hasModules: Object.keys(modules).length > 0
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
} catch (classError) {
|
|
196
|
+
console.error(`Error processing integration class ${IntegrationClass.name}:`, classError);
|
|
197
|
+
return {
|
|
198
|
+
name: `unknown-${index}`,
|
|
199
|
+
displayName: `Unknown Integration ${index}`,
|
|
200
|
+
description: 'Error processing integration',
|
|
201
|
+
category: 'Other',
|
|
202
|
+
installed: true,
|
|
203
|
+
status: 'error',
|
|
204
|
+
type: 'integration',
|
|
205
|
+
error: classError.message
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
console.log(`Successfully processed ${integrations.length} integrations:`,
|
|
211
|
+
integrations.map(i => `${i.displayName} (${i.name})`));
|
|
212
|
+
return integrations;
|
|
213
|
+
} else {
|
|
214
|
+
console.log('No integrations array found in appDefinition');
|
|
215
|
+
}
|
|
216
|
+
} catch (importError) {
|
|
217
|
+
console.error(`Error importing ${targetFile}:`, importError);
|
|
218
|
+
// Fall back to file parsing if dynamic import fails
|
|
219
|
+
return await parseBackendFile(targetFile);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log('No backend file found in any expected location');
|
|
225
|
+
=======
|
|
226
|
+
// Helper to get available integrations
|
|
227
|
+
=======
|
|
228
|
+
// Helper to get available integrations from NPM
|
|
229
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
230
|
+
async function getAvailableIntegrations() {
|
|
231
|
+
try {
|
|
232
|
+
// Search NPM registry for @friggframework/api-module-* packages
|
|
233
|
+
const searchUrl = 'https://registry.npmjs.org/-/v1/search?text=@friggframework%20api-module&size=100';
|
|
234
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
235
|
+
=======
|
|
236
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
237
|
+
|
|
238
|
+
const response = await fetch(searchUrl);
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
throw new Error(`NPM search failed: ${response.statusText}`);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const data = await response.json();
|
|
244
|
+
|
|
245
|
+
// Filter and format integration packages
|
|
246
|
+
const integrations = data.objects
|
|
247
|
+
.filter(pkg => pkg.package.name.includes('@friggframework/api-module-'))
|
|
248
|
+
.map(pkg => ({
|
|
249
|
+
name: pkg.package.name,
|
|
250
|
+
version: pkg.package.version,
|
|
251
|
+
description: pkg.package.description || 'No description available',
|
|
252
|
+
category: detectCategory(pkg.package.name, pkg.package.description || '', pkg.package.keywords || []),
|
|
253
|
+
installed: false,
|
|
254
|
+
tags: pkg.package.keywords || [],
|
|
255
|
+
npmUrl: `https://www.npmjs.com/package/${pkg.package.name}`
|
|
256
|
+
}));
|
|
257
|
+
|
|
258
|
+
console.log(`Found ${integrations.length} available integrations from NPM`);
|
|
259
|
+
return integrations;
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error('Error fetching integrations from NPM:', error);
|
|
262
|
+
// Fallback to basic list if NPM search fails
|
|
263
|
+
return [
|
|
264
|
+
{
|
|
265
|
+
name: '@friggframework/api-module-hubspot',
|
|
266
|
+
version: 'latest',
|
|
267
|
+
description: 'HubSpot CRM integration for Frigg',
|
|
268
|
+
category: 'CRM',
|
|
269
|
+
installed: false
|
|
270
|
+
}
|
|
271
|
+
];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Helper to detect integration category
|
|
276
|
+
function detectCategory(name, description, keywords) {
|
|
277
|
+
const text = `${name} ${description} ${keywords.join(' ')}`.toLowerCase();
|
|
278
|
+
|
|
279
|
+
const categoryPatterns = {
|
|
280
|
+
'CRM': ['crm', 'customer', 'salesforce', 'hubspot', 'pipedrive'],
|
|
281
|
+
'Communication': ['email', 'sms', 'chat', 'slack', 'discord', 'teams'],
|
|
282
|
+
'E-commerce': ['ecommerce', 'shop', 'store', 'payment', 'stripe', 'paypal'],
|
|
283
|
+
'Marketing': ['marketing', 'campaign', 'mailchimp', 'activecampaign'],
|
|
284
|
+
'Productivity': ['task', 'project', 'asana', 'trello', 'notion', 'jira'],
|
|
285
|
+
'Analytics': ['analytics', 'tracking', 'google', 'mixpanel', 'segment'],
|
|
286
|
+
'Support': ['support', 'helpdesk', 'ticket', 'zendesk', 'intercom'],
|
|
287
|
+
'Finance': ['accounting', 'invoice', 'quickbooks', 'xero', 'billing'],
|
|
288
|
+
'Developer Tools': ['github', 'gitlab', 'bitbucket', 'api', 'webhook'],
|
|
289
|
+
'Social Media': ['social', 'facebook', 'twitter', 'instagram', 'linkedin']
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
for (const [category, patterns] of Object.entries(categoryPatterns)) {
|
|
293
|
+
for (const pattern of patterns) {
|
|
294
|
+
if (text.includes(pattern)) {
|
|
295
|
+
return category;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return 'Other';
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Helper to get actual integrations from backend.js appDefinition
|
|
304
|
+
async function getInstalledIntegrations() {
|
|
305
|
+
try {
|
|
306
|
+
// Try multiple possible backend locations
|
|
307
|
+
const possiblePaths = [
|
|
308
|
+
path.join(process.cwd(), '../../../backend'),
|
|
309
|
+
path.join(process.cwd(), '../../backend'),
|
|
310
|
+
path.join(process.cwd(), '../backend'),
|
|
311
|
+
path.join(process.cwd(), 'backend'),
|
|
312
|
+
// Also check template backend
|
|
313
|
+
path.join(process.cwd(), '../frigg-cli/templates/backend')
|
|
314
|
+
];
|
|
315
|
+
|
|
316
|
+
for (const backendPath of possiblePaths) {
|
|
317
|
+
const backendJsPath = path.join(backendPath, 'backend.js');
|
|
318
|
+
const indexJsPath = path.join(backendPath, 'index.js');
|
|
319
|
+
|
|
320
|
+
// Try both backend.js and index.js
|
|
321
|
+
const targetFile = await fs.pathExists(backendJsPath) ? backendJsPath :
|
|
322
|
+
await fs.pathExists(indexJsPath) ? indexJsPath : null;
|
|
323
|
+
|
|
324
|
+
if (targetFile) {
|
|
325
|
+
console.log(`Found backend file at: ${targetFile}`);
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
// Dynamically import the backend file to get the actual appDefinition
|
|
329
|
+
// Use importCommonJS helper to handle both ESM and CommonJS modules
|
|
330
|
+
const backendModule = await importCommonJS(targetFile);
|
|
331
|
+
|
|
332
|
+
// Extract appDefinition - could be default export, named export, or variable
|
|
333
|
+
const appDefinition = backendModule.default?.appDefinition ||
|
|
334
|
+
backendModule.appDefinition ||
|
|
335
|
+
backendModule.default ||
|
|
336
|
+
backendModule;
|
|
337
|
+
|
|
338
|
+
if (appDefinition && appDefinition.integrations && Array.isArray(appDefinition.integrations)) {
|
|
339
|
+
console.log(`Found ${appDefinition.integrations.length} integrations in appDefinition`);
|
|
340
|
+
|
|
341
|
+
const integrations = appDefinition.integrations.map((IntegrationClass, index) => {
|
|
342
|
+
try {
|
|
343
|
+
// Get integration metadata from static properties
|
|
344
|
+
const config = IntegrationClass.Config || {};
|
|
345
|
+
const options = IntegrationClass.Options || {};
|
|
346
|
+
const modules = IntegrationClass.modules || {};
|
|
347
|
+
const display = options.display || {};
|
|
348
|
+
|
|
349
|
+
// Extract service name from class name
|
|
350
|
+
const className = IntegrationClass.name || `Integration${index}`;
|
|
351
|
+
const serviceName = className.replace(/Integration$/, '');
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
name: config.name || serviceName.toLowerCase(),
|
|
355
|
+
displayName: display.name || serviceName,
|
|
356
|
+
description: display.description || `${serviceName} integration`,
|
|
357
|
+
category: display.category || detectCategory(serviceName.toLowerCase(), display.description || '', []),
|
|
358
|
+
version: config.version || '1.0.0',
|
|
359
|
+
installed: true,
|
|
360
|
+
status: 'active',
|
|
361
|
+
type: 'integration',
|
|
362
|
+
className: className,
|
|
363
|
+
|
|
364
|
+
// Integration configuration details
|
|
365
|
+
events: config.events || [],
|
|
366
|
+
supportedVersions: config.supportedVersions || [],
|
|
367
|
+
hasUserConfig: options.hasUserConfig || false,
|
|
368
|
+
|
|
369
|
+
// Display properties
|
|
370
|
+
icon: display.icon,
|
|
371
|
+
detailsUrl: display.detailsUrl,
|
|
372
|
+
|
|
373
|
+
// API Modules information
|
|
374
|
+
apiModules: Object.keys(modules).map(key => ({
|
|
375
|
+
name: key,
|
|
376
|
+
module: modules[key]?.name || key,
|
|
377
|
+
description: `API module for ${key}`
|
|
378
|
+
})),
|
|
379
|
+
|
|
380
|
+
// Constructor details
|
|
381
|
+
constructor: {
|
|
382
|
+
name: className,
|
|
383
|
+
hasConfig: !!config,
|
|
384
|
+
hasOptions: !!options,
|
|
385
|
+
hasModules: Object.keys(modules).length > 0
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
} catch (classError) {
|
|
389
|
+
console.error(`Error processing integration class ${IntegrationClass.name}:`, classError);
|
|
390
|
+
return {
|
|
391
|
+
name: `unknown-${index}`,
|
|
392
|
+
displayName: `Unknown Integration ${index}`,
|
|
393
|
+
description: 'Error processing integration',
|
|
394
|
+
category: 'Other',
|
|
395
|
+
installed: true,
|
|
396
|
+
status: 'error',
|
|
397
|
+
type: 'integration',
|
|
398
|
+
error: classError.message
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
console.log(`Successfully processed ${integrations.length} integrations:`,
|
|
404
|
+
integrations.map(i => `${i.displayName} (${i.name})`));
|
|
405
|
+
return integrations;
|
|
406
|
+
} else {
|
|
407
|
+
console.log('No integrations array found in appDefinition');
|
|
408
|
+
}
|
|
409
|
+
} catch (importError) {
|
|
410
|
+
console.error(`Error importing ${targetFile}:`, importError);
|
|
411
|
+
// Fall back to file parsing if dynamic import fails
|
|
412
|
+
return await parseBackendFile(targetFile);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
<<<<<<< HEAD
|
|
418
|
+
<<<<<<< HEAD
|
|
419
|
+
console.log('No backend file found in any expected location');
|
|
420
|
+
=======
|
|
421
|
+
<<<<<<< HEAD
|
|
422
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
423
|
+
=======
|
|
424
|
+
console.log('No backend file found in any expected location');
|
|
425
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
426
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
427
|
+
=======
|
|
428
|
+
console.log('No backend file found in any expected location');
|
|
429
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
430
|
+
return [];
|
|
431
|
+
} catch (error) {
|
|
432
|
+
console.error('Error reading installed integrations:', error);
|
|
433
|
+
return [];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
<<<<<<< HEAD
|
|
438
|
+
<<<<<<< HEAD
|
|
439
|
+
=======
|
|
440
|
+
<<<<<<< HEAD
|
|
441
|
+
<<<<<<< HEAD
|
|
442
|
+
=======
|
|
443
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
444
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
445
|
+
=======
|
|
446
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
447
|
+
// Fallback function to parse backend file if dynamic import fails
|
|
448
|
+
async function parseBackendFile(filePath) {
|
|
449
|
+
try {
|
|
450
|
+
const backendContent = await fs.readFile(filePath, 'utf8');
|
|
451
|
+
const integrations = [];
|
|
452
|
+
<<<<<<< HEAD
|
|
453
|
+
<<<<<<< HEAD
|
|
454
|
+
=======
|
|
455
|
+
<<<<<<< HEAD
|
|
456
|
+
|
|
457
|
+
// Extract integration imports
|
|
458
|
+
const importMatches = backendContent.match(/(?:const|let|var)\s+(\w+Integration)\s*=\s*require\(['"]([^'"]+)['"]\)/g) || [];
|
|
459
|
+
|
|
460
|
+
=======
|
|
461
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
462
|
+
=======
|
|
463
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
464
|
+
|
|
465
|
+
// Extract integration imports - handle both require and import statements
|
|
466
|
+
const requireMatches = backendContent.match(/(?:const|let|var)\s+(\w+Integration)\s*=\s*require\(['"]([^'"]+)['"]\)/g) || [];
|
|
467
|
+
const importMatches = backendContent.match(/import\s+(?:\*\s+as\s+)?(\w+Integration)\s+from\s+['"]([^'"]+)['"]/g) || [];
|
|
468
|
+
const allMatches = [...requireMatches, ...importMatches];
|
|
469
|
+
|
|
470
|
+
<<<<<<< HEAD
|
|
471
|
+
<<<<<<< HEAD
|
|
472
|
+
for (const match of allMatches) {
|
|
473
|
+
=======
|
|
474
|
+
<<<<<<< HEAD
|
|
475
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
476
|
+
for (const match of importMatches) {
|
|
477
|
+
=======
|
|
478
|
+
for (const match of allMatches) {
|
|
479
|
+
>>>>>>> d6114470 (feat: add comprehensive DDD/Hexagonal architecture RFC series)
|
|
480
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
481
|
+
=======
|
|
482
|
+
for (const match of allMatches) {
|
|
483
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
484
|
+
const nameMatch = match.match(/(\w+Integration)/);
|
|
485
|
+
if (nameMatch) {
|
|
486
|
+
const integrationName = nameMatch[1];
|
|
487
|
+
const serviceName = integrationName.replace('Integration', '');
|
|
488
|
+
<<<<<<< HEAD
|
|
489
|
+
<<<<<<< HEAD
|
|
490
|
+
|
|
491
|
+
=======
|
|
492
|
+
<<<<<<< HEAD
|
|
493
|
+
|
|
494
|
+
=======
|
|
495
|
+
|
|
496
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
497
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
498
|
+
=======
|
|
499
|
+
|
|
500
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
501
|
+
// Check if this integration is in the integrations array
|
|
502
|
+
if (backendContent.includes(integrationName)) {
|
|
503
|
+
integrations.push({
|
|
504
|
+
name: serviceName.toLowerCase(),
|
|
505
|
+
displayName: serviceName,
|
|
506
|
+
description: `${serviceName} integration`,
|
|
507
|
+
category: detectCategory(serviceName.toLowerCase(), '', []),
|
|
508
|
+
installed: true,
|
|
509
|
+
status: 'active',
|
|
510
|
+
type: 'integration',
|
|
511
|
+
className: integrationName,
|
|
512
|
+
constructor: {
|
|
513
|
+
name: integrationName,
|
|
514
|
+
hasConfig: true,
|
|
515
|
+
hasOptions: true,
|
|
516
|
+
hasModules: true
|
|
517
|
+
},
|
|
518
|
+
note: 'Parsed from file (dynamic loading failed)'
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
<<<<<<< HEAD
|
|
524
|
+
<<<<<<< HEAD
|
|
525
|
+
|
|
526
|
+
=======
|
|
527
|
+
<<<<<<< HEAD
|
|
528
|
+
|
|
529
|
+
=======
|
|
530
|
+
|
|
531
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
532
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
533
|
+
=======
|
|
534
|
+
|
|
535
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
536
|
+
return integrations;
|
|
537
|
+
} catch (error) {
|
|
538
|
+
console.error('Error parsing backend file:', error);
|
|
539
|
+
return [];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
<<<<<<< HEAD
|
|
544
|
+
<<<<<<< HEAD
|
|
545
|
+
=======
|
|
546
|
+
<<<<<<< HEAD
|
|
547
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
548
|
+
=======
|
|
549
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
550
|
+
// List all integrations
|
|
551
|
+
router.get('/', async (req, res) => {
|
|
552
|
+
try {
|
|
553
|
+
const [availableApiModules, installedIntegrations] = await Promise.all([
|
|
554
|
+
<<<<<<< HEAD
|
|
555
|
+
<<<<<<< HEAD
|
|
556
|
+
=======
|
|
557
|
+
=======
|
|
558
|
+
// List all integrations
|
|
559
|
+
router.get('/', async (req, res) => {
|
|
560
|
+
try {
|
|
561
|
+
const [available, installed] = await Promise.all([
|
|
562
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
563
|
+
=======
|
|
564
|
+
// List all integrations
|
|
565
|
+
router.get('/', async (req, res) => {
|
|
566
|
+
try {
|
|
567
|
+
const [availableApiModules, installedIntegrations] = await Promise.all([
|
|
568
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
569
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
570
|
+
=======
|
|
571
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
572
|
+
getAvailableIntegrations(),
|
|
573
|
+
getInstalledIntegrations()
|
|
574
|
+
]);
|
|
575
|
+
|
|
576
|
+
<<<<<<< HEAD
|
|
577
|
+
<<<<<<< HEAD
|
|
578
|
+
=======
|
|
579
|
+
<<<<<<< HEAD
|
|
580
|
+
<<<<<<< HEAD
|
|
581
|
+
=======
|
|
582
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
583
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
584
|
+
=======
|
|
585
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
586
|
+
// Format available API modules (not yet integrations)
|
|
587
|
+
const formattedAvailable = availableApiModules.map(apiModule => ({
|
|
588
|
+
...apiModule,
|
|
589
|
+
displayName: apiModule.name.replace('@friggframework/api-module-', '').replace(/-/g, ' '),
|
|
590
|
+
installed: false,
|
|
591
|
+
status: 'available',
|
|
592
|
+
type: 'api-module' // These are just API modules, not full integrations
|
|
593
|
+
}));
|
|
594
|
+
|
|
595
|
+
// Actual integrations already properly formatted from appDefinition
|
|
596
|
+
const formattedIntegrations = installedIntegrations.map(integration => ({
|
|
597
|
+
...integration,
|
|
598
|
+
installed: true,
|
|
599
|
+
status: integration.status || 'active'
|
|
600
|
+
}));
|
|
601
|
+
<<<<<<< HEAD
|
|
602
|
+
<<<<<<< HEAD
|
|
603
|
+
=======
|
|
604
|
+
<<<<<<< HEAD
|
|
605
|
+
|
|
606
|
+
res.json({
|
|
607
|
+
// Main integrations array contains actual integrations from appDefinition
|
|
608
|
+
integrations: formattedIntegrations,
|
|
609
|
+
|
|
610
|
+
// Available API modules that could become integrations
|
|
611
|
+
availableApiModules: formattedAvailable,
|
|
612
|
+
|
|
613
|
+
// Summary counts
|
|
614
|
+
total: formattedIntegrations.length + formattedAvailable.length,
|
|
615
|
+
activeIntegrations: formattedIntegrations.length,
|
|
616
|
+
availableModules: formattedAvailable.length,
|
|
617
|
+
|
|
618
|
+
// Metadata about the response
|
|
619
|
+
source: 'appDefinition',
|
|
620
|
+
message: formattedIntegrations.length > 0
|
|
621
|
+
? `Found ${formattedIntegrations.length} active integrations from backend appDefinition`
|
|
622
|
+
: 'No integrations found in backend appDefinition'
|
|
623
|
+
=======
|
|
624
|
+
// Merge lists
|
|
625
|
+
const installedNames = installed.map(i => i.name);
|
|
626
|
+
const allIntegrations = [
|
|
627
|
+
...installed,
|
|
628
|
+
...available.filter(a => !installedNames.includes(a.name))
|
|
629
|
+
];
|
|
630
|
+
|
|
631
|
+
res.json({
|
|
632
|
+
integrations: allIntegrations,
|
|
633
|
+
total: allIntegrations.length
|
|
634
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
635
|
+
=======
|
|
636
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
637
|
+
=======
|
|
638
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
639
|
+
|
|
640
|
+
res.json({
|
|
641
|
+
// Main integrations array contains actual integrations from appDefinition
|
|
642
|
+
integrations: formattedIntegrations,
|
|
643
|
+
|
|
644
|
+
// Available API modules that could become integrations
|
|
645
|
+
availableApiModules: formattedAvailable,
|
|
646
|
+
|
|
647
|
+
// Summary counts
|
|
648
|
+
total: formattedIntegrations.length + formattedAvailable.length,
|
|
649
|
+
activeIntegrations: formattedIntegrations.length,
|
|
650
|
+
availableModules: formattedAvailable.length,
|
|
651
|
+
|
|
652
|
+
// Metadata about the response
|
|
653
|
+
source: 'appDefinition',
|
|
654
|
+
message: formattedIntegrations.length > 0
|
|
655
|
+
? `Found ${formattedIntegrations.length} active integrations from backend appDefinition`
|
|
656
|
+
: 'No integrations found in backend appDefinition'
|
|
657
|
+
<<<<<<< HEAD
|
|
658
|
+
<<<<<<< HEAD
|
|
659
|
+
=======
|
|
660
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
661
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
662
|
+
=======
|
|
663
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
664
|
+
});
|
|
665
|
+
} catch (error) {
|
|
666
|
+
res.status(500).json({
|
|
667
|
+
error: error.message,
|
|
668
|
+
details: 'Failed to fetch integrations'
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
// Install an integration
|
|
674
|
+
router.post('/install', async (req, res) => {
|
|
675
|
+
const { packageName } = req.body;
|
|
676
|
+
|
|
677
|
+
if (!packageName) {
|
|
678
|
+
return res.status(400).json({
|
|
679
|
+
error: 'Package name is required'
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
try {
|
|
684
|
+
// Broadcast installation start
|
|
685
|
+
wsHandler.broadcast('integration-install', {
|
|
686
|
+
status: 'installing',
|
|
687
|
+
packageName,
|
|
688
|
+
message: `Installing ${packageName}...`
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
// Run frigg install command
|
|
692
|
+
const { stdout, stderr } = await execAsync(
|
|
693
|
+
`npx frigg install ${packageName}`,
|
|
694
|
+
{ cwd: path.join(process.cwd(), '../../../backend') }
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
// Broadcast success
|
|
698
|
+
wsHandler.broadcast('integration-install', {
|
|
699
|
+
status: 'installed',
|
|
700
|
+
packageName,
|
|
701
|
+
message: `Successfully installed ${packageName}`,
|
|
702
|
+
output: stdout
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
res.json({
|
|
706
|
+
status: 'success',
|
|
707
|
+
message: `Integration ${packageName} installed successfully`,
|
|
708
|
+
output: stdout
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
} catch (error) {
|
|
712
|
+
// Broadcast error
|
|
713
|
+
wsHandler.broadcast('integration-install', {
|
|
714
|
+
status: 'error',
|
|
715
|
+
packageName,
|
|
716
|
+
message: `Failed to install ${packageName}`,
|
|
717
|
+
error: error.message
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
res.status(500).json({
|
|
721
|
+
error: error.message,
|
|
722
|
+
details: 'Failed to install integration',
|
|
723
|
+
stderr: error.stderr
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
// Configure an integration
|
|
729
|
+
router.post('/:integrationName/configure', async (req, res) => {
|
|
730
|
+
const { integrationName } = req.params;
|
|
731
|
+
const { config } = req.body;
|
|
732
|
+
|
|
733
|
+
try {
|
|
734
|
+
// This would typically update the integration configuration
|
|
735
|
+
// For now, we'll store it in a config file
|
|
736
|
+
const configPath = path.join(
|
|
737
|
+
process.cwd(),
|
|
738
|
+
'../../../backend',
|
|
739
|
+
'config',
|
|
740
|
+
'integrations',
|
|
741
|
+
`${integrationName}.json`
|
|
742
|
+
);
|
|
743
|
+
|
|
744
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
745
|
+
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
746
|
+
|
|
747
|
+
res.json({
|
|
748
|
+
status: 'success',
|
|
749
|
+
message: `Configuration saved for ${integrationName}`,
|
|
750
|
+
config
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
} catch (error) {
|
|
754
|
+
res.status(500).json({
|
|
755
|
+
error: error.message,
|
|
756
|
+
details: 'Failed to configure integration'
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
// Get integration configuration
|
|
762
|
+
router.get('/:integrationName/config', async (req, res) => {
|
|
763
|
+
const { integrationName } = req.params;
|
|
764
|
+
|
|
765
|
+
try {
|
|
766
|
+
const configPath = path.join(
|
|
767
|
+
process.cwd(),
|
|
768
|
+
'../../../backend',
|
|
769
|
+
'config',
|
|
770
|
+
'integrations',
|
|
771
|
+
`${integrationName}.json`
|
|
772
|
+
);
|
|
773
|
+
|
|
774
|
+
if (await fs.pathExists(configPath)) {
|
|
775
|
+
const config = await fs.readJson(configPath);
|
|
776
|
+
res.json({ config });
|
|
777
|
+
} else {
|
|
778
|
+
res.json({ config: {} });
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
} catch (error) {
|
|
782
|
+
res.status(500).json({
|
|
783
|
+
error: error.message,
|
|
784
|
+
details: 'Failed to read integration configuration'
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
});
|
|
788
|
+
|
|
789
|
+
// Remove an integration
|
|
790
|
+
router.delete('/:integrationName', async (req, res) => {
|
|
791
|
+
const { integrationName } = req.params;
|
|
792
|
+
|
|
793
|
+
try {
|
|
794
|
+
// Broadcast removal start
|
|
795
|
+
wsHandler.broadcast('integration-remove', {
|
|
796
|
+
status: 'removing',
|
|
797
|
+
packageName: integrationName,
|
|
798
|
+
message: `Removing ${integrationName}...`
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
// Remove the package
|
|
802
|
+
const { stdout, stderr } = await execAsync(
|
|
803
|
+
`npm uninstall ${integrationName}`,
|
|
804
|
+
{ cwd: path.join(process.cwd(), '../../../backend') }
|
|
805
|
+
);
|
|
806
|
+
|
|
807
|
+
// Remove config if exists
|
|
808
|
+
const configPath = path.join(
|
|
809
|
+
process.cwd(),
|
|
810
|
+
'../../../backend',
|
|
811
|
+
'config',
|
|
812
|
+
'integrations',
|
|
813
|
+
`${integrationName}.json`
|
|
814
|
+
);
|
|
815
|
+
<<<<<<< HEAD
|
|
816
|
+
<<<<<<< HEAD
|
|
817
|
+
|
|
818
|
+
=======
|
|
819
|
+
<<<<<<< HEAD
|
|
820
|
+
|
|
821
|
+
=======
|
|
822
|
+
|
|
823
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
824
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
825
|
+
=======
|
|
826
|
+
|
|
827
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
828
|
+
if (await fs.pathExists(configPath)) {
|
|
829
|
+
await fs.remove(configPath);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// Broadcast success
|
|
833
|
+
wsHandler.broadcast('integration-remove', {
|
|
834
|
+
status: 'removed',
|
|
835
|
+
packageName: integrationName,
|
|
836
|
+
message: `Successfully removed ${integrationName}`
|
|
837
|
+
});
|
|
838
|
+
|
|
839
|
+
res.json({
|
|
840
|
+
status: 'success',
|
|
841
|
+
message: `Integration ${integrationName} removed successfully`
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
} catch (error) {
|
|
845
|
+
// Broadcast error
|
|
846
|
+
wsHandler.broadcast('integration-remove', {
|
|
847
|
+
status: 'error',
|
|
848
|
+
packageName: integrationName,
|
|
849
|
+
message: `Failed to remove ${integrationName}`,
|
|
850
|
+
error: error.message
|
|
851
|
+
});
|
|
852
|
+
|
|
853
|
+
res.status(500).json({
|
|
854
|
+
error: error.message,
|
|
855
|
+
details: 'Failed to remove integration'
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
<<<<<<< HEAD
|
|
861
|
+
<<<<<<< HEAD
|
|
862
|
+
export { getInstalledIntegrations }
|
|
863
|
+
=======
|
|
864
|
+
<<<<<<< HEAD
|
|
865
|
+
<<<<<<< HEAD
|
|
866
|
+
export { getInstalledIntegrations }
|
|
867
|
+
=======
|
|
868
|
+
>>>>>>> 652520a5 (Claude Flow RFC related development)
|
|
869
|
+
=======
|
|
870
|
+
export { getInstalledIntegrations }
|
|
871
|
+
>>>>>>> f153939e (refactor: clean up CLI help display and remove unused dependencies)
|
|
872
|
+
>>>>>>> 860052b4 (feat: integrate complete management-ui and additional features)
|
|
873
|
+
=======
|
|
874
|
+
export { getInstalledIntegrations }
|
|
875
|
+
>>>>>>> 7e97f01c (fix: resolve ui-command merge conflicts and update package.json)
|
|
876
|
+
export default router
|