@friggframework/devtools 2.0.0-next.3 → 2.0.0-next.31
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/build-command/index.js +54 -0
- package/frigg-cli/deploy-command/index.js +36 -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/generate-iam-command.js +115 -0
- package/frigg-cli/index.js +47 -1
- package/frigg-cli/index.test.js +1 -4
- 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/install-command/index.js +1 -4
- package/frigg-cli/package.json +51 -0
- package/frigg-cli/start-command/index.js +24 -4
- 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 +16 -17
- 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/AWS-DISCOVERY-TROUBLESHOOTING.md +245 -0
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +596 -0
- package/infrastructure/DEPLOYMENT-INSTRUCTIONS.md +268 -0
- package/infrastructure/GENERATE-IAM-DOCS.md +253 -0
- package/infrastructure/IAM-POLICY-TEMPLATES.md +176 -0
- package/infrastructure/README-TESTING.md +332 -0
- package/infrastructure/README.md +421 -0
- package/infrastructure/WEBSOCKET-CONFIGURATION.md +105 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/aws-discovery.js +568 -0
- package/infrastructure/aws-discovery.test.js +373 -0
- package/infrastructure/build-time-discovery.js +206 -0
- package/infrastructure/build-time-discovery.test.js +375 -0
- package/infrastructure/create-frigg-infrastructure.js +3 -5
- package/infrastructure/frigg-deployment-iam-stack.yaml +379 -0
- package/infrastructure/iam-generator.js +687 -0
- package/infrastructure/iam-generator.test.js +169 -0
- package/infrastructure/iam-policy-basic.json +212 -0
- package/infrastructure/iam-policy-full.json +282 -0
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/run-discovery.js +110 -0
- package/infrastructure/serverless-template.js +923 -113
- package/infrastructure/serverless-template.test.js +541 -0
- 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/index.html +13 -0
- 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/assets/FriggLogo.svg +1 -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 +17 -9
- package/infrastructure/app-handler-helpers.js +0 -57
- package/infrastructure/backend-utils.js +0 -90
- package/infrastructure/routers/auth.js +0 -26
- package/infrastructure/routers/integration-defined-routers.js +0 -37
- package/infrastructure/routers/middleware/loadUser.js +0 -15
- package/infrastructure/routers/middleware/requireLoggedInUser.js +0 -12
- package/infrastructure/routers/user.js +0 -41
- package/infrastructure/routers/websocket.js +0 -55
- package/infrastructure/workers/integration-defined-workers.js +0 -24
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import NodeCache from 'node-cache';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* NPM Registry Service
|
|
7
|
+
* Handles fetching and caching of @friggframework/api-module-* packages
|
|
8
|
+
*/
|
|
9
|
+
class NPMRegistryService {
|
|
10
|
+
constructor() {
|
|
11
|
+
// Cache with 1 hour TTL by default
|
|
12
|
+
this.cache = new NodeCache({
|
|
13
|
+
stdTTL: 3600,
|
|
14
|
+
checkperiod: 600,
|
|
15
|
+
useClones: false
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
this.npmRegistryUrl = 'https://registry.npmjs.org';
|
|
19
|
+
this.searchUrl = `${this.npmRegistryUrl}/-/v1/search`;
|
|
20
|
+
this.packageScope = '@friggframework';
|
|
21
|
+
this.modulePrefix = 'api-module-';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Search for all @friggframework/api-module-* packages
|
|
26
|
+
* @param {Object} options - Search options
|
|
27
|
+
* @param {boolean} options.includePrerelease - Include prerelease versions
|
|
28
|
+
* @param {boolean} options.forceRefresh - Force cache refresh
|
|
29
|
+
* @returns {Promise<Array>} Array of package information
|
|
30
|
+
*/
|
|
31
|
+
async searchApiModules(options = {}) {
|
|
32
|
+
const cacheKey = `api-modules-${JSON.stringify(options)}`;
|
|
33
|
+
|
|
34
|
+
// Check cache first unless force refresh is requested
|
|
35
|
+
if (!options.forceRefresh) {
|
|
36
|
+
const cached = this.cache.get(cacheKey);
|
|
37
|
+
if (cached) {
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
// Search for packages matching our pattern
|
|
44
|
+
const searchQuery = `${this.packageScope}/${this.modulePrefix}`;
|
|
45
|
+
const response = await axios.get(this.searchUrl, {
|
|
46
|
+
params: {
|
|
47
|
+
text: searchQuery,
|
|
48
|
+
size: 250, // Get up to 250 results
|
|
49
|
+
quality: 0.65,
|
|
50
|
+
popularity: 0.98,
|
|
51
|
+
maintenance: 0.5
|
|
52
|
+
},
|
|
53
|
+
timeout: 10000
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const packages = response.data.objects
|
|
57
|
+
.filter(obj => obj.package.name.startsWith(`${this.packageScope}/${this.modulePrefix}`))
|
|
58
|
+
.map(obj => this.formatPackageInfo(obj.package));
|
|
59
|
+
|
|
60
|
+
// Filter out prereleases if requested
|
|
61
|
+
const filtered = options.includePrerelease
|
|
62
|
+
? packages
|
|
63
|
+
: packages.filter(pkg => !semver.prerelease(pkg.version));
|
|
64
|
+
|
|
65
|
+
// Cache the results
|
|
66
|
+
this.cache.set(cacheKey, filtered);
|
|
67
|
+
|
|
68
|
+
return filtered;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error('Error searching NPM registry:', error);
|
|
71
|
+
throw new Error(`Failed to search NPM registry: ${error.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get detailed information about a specific package
|
|
77
|
+
* @param {string} packageName - Full package name (e.g., @friggframework/api-module-hubspot)
|
|
78
|
+
* @param {string} version - Specific version or 'latest'
|
|
79
|
+
* @returns {Promise<Object>} Detailed package information
|
|
80
|
+
*/
|
|
81
|
+
async getPackageDetails(packageName, version = 'latest') {
|
|
82
|
+
const cacheKey = `package-details-${packageName}-${version}`;
|
|
83
|
+
|
|
84
|
+
const cached = this.cache.get(cacheKey);
|
|
85
|
+
if (cached) {
|
|
86
|
+
return cached;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const url = `${this.npmRegistryUrl}/${packageName}`;
|
|
91
|
+
const response = await axios.get(url, { timeout: 10000 });
|
|
92
|
+
|
|
93
|
+
const data = response.data;
|
|
94
|
+
const versionData = version === 'latest'
|
|
95
|
+
? data.versions[data['dist-tags'].latest]
|
|
96
|
+
: data.versions[version];
|
|
97
|
+
|
|
98
|
+
if (!versionData) {
|
|
99
|
+
throw new Error(`Version ${version} not found for package ${packageName}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const details = {
|
|
103
|
+
name: data.name,
|
|
104
|
+
version: versionData.version,
|
|
105
|
+
description: versionData.description || data.description,
|
|
106
|
+
keywords: versionData.keywords || data.keywords || [],
|
|
107
|
+
homepage: versionData.homepage || data.homepage,
|
|
108
|
+
repository: versionData.repository || data.repository,
|
|
109
|
+
author: versionData.author || data.author,
|
|
110
|
+
license: versionData.license || data.license,
|
|
111
|
+
dependencies: versionData.dependencies || {},
|
|
112
|
+
peerDependencies: versionData.peerDependencies || {},
|
|
113
|
+
publishedAt: data.time[versionData.version],
|
|
114
|
+
versions: Object.keys(data.versions).reverse(),
|
|
115
|
+
distTags: data['dist-tags'],
|
|
116
|
+
readme: data.readme,
|
|
117
|
+
// Extract integration name from package name
|
|
118
|
+
integrationName: this.extractIntegrationName(data.name),
|
|
119
|
+
// Additional metadata
|
|
120
|
+
isDeprecated: versionData.deprecated || false,
|
|
121
|
+
engines: versionData.engines || {},
|
|
122
|
+
maintainers: data.maintainers || []
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Cache the results
|
|
126
|
+
this.cache.set(cacheKey, details);
|
|
127
|
+
|
|
128
|
+
return details;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(`Error fetching package details for ${packageName}:`, error);
|
|
131
|
+
throw new Error(`Failed to fetch package details: ${error.message}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get all available versions for a package
|
|
137
|
+
* @param {string} packageName - Full package name
|
|
138
|
+
* @returns {Promise<Array>} Array of version information
|
|
139
|
+
*/
|
|
140
|
+
async getPackageVersions(packageName) {
|
|
141
|
+
const cacheKey = `package-versions-${packageName}`;
|
|
142
|
+
|
|
143
|
+
const cached = this.cache.get(cacheKey);
|
|
144
|
+
if (cached) {
|
|
145
|
+
return cached;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const url = `${this.npmRegistryUrl}/${packageName}`;
|
|
150
|
+
const response = await axios.get(url, { timeout: 10000 });
|
|
151
|
+
|
|
152
|
+
const versions = Object.entries(response.data.versions)
|
|
153
|
+
.map(([version, data]) => ({
|
|
154
|
+
version,
|
|
155
|
+
publishedAt: response.data.time[version],
|
|
156
|
+
deprecated: data.deprecated || false,
|
|
157
|
+
prerelease: !!semver.prerelease(version),
|
|
158
|
+
major: semver.major(version),
|
|
159
|
+
minor: semver.minor(version),
|
|
160
|
+
patch: semver.patch(version)
|
|
161
|
+
}))
|
|
162
|
+
.sort((a, b) => semver.rcompare(a.version, b.version));
|
|
163
|
+
|
|
164
|
+
// Cache the results
|
|
165
|
+
this.cache.set(cacheKey, versions);
|
|
166
|
+
|
|
167
|
+
return versions;
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(`Error fetching versions for ${packageName}:`, error);
|
|
170
|
+
throw new Error(`Failed to fetch package versions: ${error.message}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Check compatibility between a package version and Frigg core version
|
|
176
|
+
* @param {string} packageName - Package name to check
|
|
177
|
+
* @param {string} packageVersion - Package version
|
|
178
|
+
* @param {string} friggVersion - Frigg core version
|
|
179
|
+
* @returns {Promise<Object>} Compatibility information
|
|
180
|
+
*/
|
|
181
|
+
async checkCompatibility(packageName, packageVersion, friggVersion) {
|
|
182
|
+
try {
|
|
183
|
+
const details = await this.getPackageDetails(packageName, packageVersion);
|
|
184
|
+
|
|
185
|
+
const compatibility = {
|
|
186
|
+
compatible: true,
|
|
187
|
+
warnings: [],
|
|
188
|
+
errors: [],
|
|
189
|
+
recommendations: []
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Check peer dependencies
|
|
193
|
+
if (details.peerDependencies['@friggframework/core']) {
|
|
194
|
+
const requiredVersion = details.peerDependencies['@friggframework/core'];
|
|
195
|
+
if (!semver.satisfies(friggVersion, requiredVersion)) {
|
|
196
|
+
compatibility.compatible = false;
|
|
197
|
+
compatibility.errors.push(
|
|
198
|
+
`Package requires @friggframework/core ${requiredVersion}, but current version is ${friggVersion}`
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Check engine requirements
|
|
204
|
+
if (details.engines?.node) {
|
|
205
|
+
const nodeVersion = process.version;
|
|
206
|
+
if (!semver.satisfies(nodeVersion, details.engines.node)) {
|
|
207
|
+
compatibility.warnings.push(
|
|
208
|
+
`Package requires Node.js ${details.engines.node}, current version is ${nodeVersion}`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Check for deprecated versions
|
|
214
|
+
if (details.isDeprecated) {
|
|
215
|
+
compatibility.warnings.push('This version is deprecated');
|
|
216
|
+
compatibility.recommendations.push('Consider upgrading to the latest version');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Check if it's a prerelease version
|
|
220
|
+
if (semver.prerelease(packageVersion)) {
|
|
221
|
+
compatibility.warnings.push('This is a prerelease version and may be unstable');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return compatibility;
|
|
225
|
+
} catch (error) {
|
|
226
|
+
console.error('Error checking compatibility:', error);
|
|
227
|
+
throw new Error(`Failed to check compatibility: ${error.message}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get grouped modules by integration type
|
|
233
|
+
* @returns {Promise<Object>} Modules grouped by type
|
|
234
|
+
*/
|
|
235
|
+
async getModulesByType() {
|
|
236
|
+
const modules = await this.searchApiModules();
|
|
237
|
+
|
|
238
|
+
const grouped = modules.reduce((acc, module) => {
|
|
239
|
+
const type = this.categorizeModule(module);
|
|
240
|
+
if (!acc[type]) {
|
|
241
|
+
acc[type] = [];
|
|
242
|
+
}
|
|
243
|
+
acc[type].push(module);
|
|
244
|
+
return acc;
|
|
245
|
+
}, {});
|
|
246
|
+
|
|
247
|
+
return grouped;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Clear the cache
|
|
252
|
+
* @param {string} pattern - Optional pattern to match cache keys
|
|
253
|
+
*/
|
|
254
|
+
clearCache(pattern = null) {
|
|
255
|
+
if (pattern) {
|
|
256
|
+
const keys = this.cache.keys();
|
|
257
|
+
keys.forEach(key => {
|
|
258
|
+
if (key.includes(pattern)) {
|
|
259
|
+
this.cache.del(key);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
this.cache.flushAll();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get cache statistics
|
|
269
|
+
* @returns {Object} Cache statistics
|
|
270
|
+
*/
|
|
271
|
+
getCacheStats() {
|
|
272
|
+
return {
|
|
273
|
+
keys: this.cache.keys().length,
|
|
274
|
+
hits: this.cache.getStats().hits,
|
|
275
|
+
misses: this.cache.getStats().misses,
|
|
276
|
+
ksize: this.cache.getStats().ksize,
|
|
277
|
+
vsize: this.cache.getStats().vsize
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Format package information for API response
|
|
283
|
+
* @private
|
|
284
|
+
*/
|
|
285
|
+
formatPackageInfo(pkg) {
|
|
286
|
+
return {
|
|
287
|
+
name: pkg.name,
|
|
288
|
+
version: pkg.version,
|
|
289
|
+
description: pkg.description,
|
|
290
|
+
keywords: pkg.keywords || [],
|
|
291
|
+
author: pkg.author,
|
|
292
|
+
publisher: pkg.publisher,
|
|
293
|
+
date: pkg.date,
|
|
294
|
+
links: pkg.links,
|
|
295
|
+
integrationName: this.extractIntegrationName(pkg.name),
|
|
296
|
+
category: this.categorizeModule(pkg)
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Extract integration name from package name
|
|
302
|
+
* @private
|
|
303
|
+
*/
|
|
304
|
+
extractIntegrationName(packageName) {
|
|
305
|
+
return packageName
|
|
306
|
+
.replace(`${this.packageScope}/${this.modulePrefix}`, '')
|
|
307
|
+
.replace(/-/g, ' ')
|
|
308
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Categorize module based on keywords and name
|
|
313
|
+
* @private
|
|
314
|
+
*/
|
|
315
|
+
categorizeModule(module) {
|
|
316
|
+
const name = module.name?.toLowerCase() || '';
|
|
317
|
+
const keywords = module.keywords?.map(k => k.toLowerCase()) || [];
|
|
318
|
+
const allTerms = [...keywords, name];
|
|
319
|
+
|
|
320
|
+
// Categories based on common integration types
|
|
321
|
+
const categories = {
|
|
322
|
+
'CRM': ['crm', 'customer', 'salesforce', 'hubspot', 'pipedrive'],
|
|
323
|
+
'Communication': ['email', 'sms', 'chat', 'messaging', 'slack', 'discord', 'twilio'],
|
|
324
|
+
'E-commerce': ['ecommerce', 'shop', 'store', 'payment', 'stripe', 'paypal', 'shopify'],
|
|
325
|
+
'Analytics': ['analytics', 'tracking', 'google-analytics', 'mixpanel', 'segment'],
|
|
326
|
+
'Marketing': ['marketing', 'mailchimp', 'sendgrid', 'campaign', 'automation'],
|
|
327
|
+
'Social Media': ['social', 'facebook', 'twitter', 'instagram', 'linkedin'],
|
|
328
|
+
'Project Management': ['project', 'task', 'jira', 'trello', 'asana', 'monday'],
|
|
329
|
+
'Storage': ['storage', 'file', 'dropbox', 'google-drive', 's3', 'box'],
|
|
330
|
+
'Development': ['github', 'gitlab', 'bitbucket', 'git', 'ci', 'cd'],
|
|
331
|
+
'Other': []
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
for (const [category, terms] of Object.entries(categories)) {
|
|
335
|
+
if (category === 'Other') continue;
|
|
336
|
+
|
|
337
|
+
if (terms.some(term => allTerms.some(t => t.includes(term)))) {
|
|
338
|
+
return category;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return 'Other';
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Export singleton instance
|
|
347
|
+
export default new NPMRegistryService();
|