@friggframework/devtools 2.0.0-next.6 → 2.0.0-next.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/frigg-cli/README.md +1289 -0
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +279 -0
  3. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +649 -0
  4. package/frigg-cli/__tests__/unit/commands/deploy.test.js +320 -0
  5. package/frigg-cli/__tests__/unit/commands/doctor.test.js +309 -0
  6. package/frigg-cli/__tests__/unit/commands/install.test.js +400 -0
  7. package/frigg-cli/__tests__/unit/commands/ui.test.js +346 -0
  8. package/frigg-cli/__tests__/unit/dependencies.test.js +74 -0
  9. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +397 -0
  10. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +345 -0
  11. package/frigg-cli/__tests__/unit/version-detection.test.js +171 -0
  12. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  13. package/frigg-cli/__tests__/utils/prisma-mock.js +194 -0
  14. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  15. package/frigg-cli/__tests__/utils/test-setup.js +287 -0
  16. package/frigg-cli/build-command/index.js +53 -14
  17. package/frigg-cli/db-setup-command/index.js +246 -0
  18. package/frigg-cli/deploy-command/SPEC-DEPLOY-DRY-RUN.md +981 -0
  19. package/frigg-cli/deploy-command/index.js +295 -17
  20. package/frigg-cli/doctor-command/index.js +335 -0
  21. package/frigg-cli/generate-command/__tests__/generate-command.test.js +301 -0
  22. package/frigg-cli/generate-command/azure-generator.js +43 -0
  23. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  24. package/frigg-cli/generate-command/index.js +332 -0
  25. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  26. package/frigg-cli/generate-iam-command.js +118 -0
  27. package/frigg-cli/index.js +142 -1
  28. package/frigg-cli/index.test.js +1 -4
  29. package/frigg-cli/init-command/backend-first-handler.js +756 -0
  30. package/frigg-cli/init-command/index.js +93 -0
  31. package/frigg-cli/init-command/template-handler.js +143 -0
  32. package/frigg-cli/install-command/index.js +1 -4
  33. package/frigg-cli/jest.config.js +124 -0
  34. package/frigg-cli/package.json +63 -0
  35. package/frigg-cli/repair-command/index.js +564 -0
  36. package/frigg-cli/start-command/index.js +125 -6
  37. package/frigg-cli/start-command/start-command.test.js +297 -0
  38. package/frigg-cli/test/init-command.test.js +180 -0
  39. package/frigg-cli/test/npm-registry.test.js +319 -0
  40. package/frigg-cli/ui-command/index.js +154 -0
  41. package/frigg-cli/utils/app-resolver.js +319 -0
  42. package/frigg-cli/utils/backend-path.js +16 -17
  43. package/frigg-cli/utils/database-validator.js +167 -0
  44. package/frigg-cli/utils/error-messages.js +329 -0
  45. package/frigg-cli/utils/npm-registry.js +167 -0
  46. package/frigg-cli/utils/process-manager.js +199 -0
  47. package/frigg-cli/utils/repo-detection.js +405 -0
  48. package/infrastructure/ARCHITECTURE.md +487 -0
  49. package/infrastructure/CLAUDE.md +481 -0
  50. package/infrastructure/HEALTH.md +468 -0
  51. package/infrastructure/README.md +522 -0
  52. package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
  53. package/infrastructure/__tests__/helpers/test-utils.js +277 -0
  54. package/infrastructure/__tests__/postgres-config.test.js +914 -0
  55. package/infrastructure/__tests__/template-generation.test.js +687 -0
  56. package/infrastructure/create-frigg-infrastructure.js +129 -20
  57. package/infrastructure/docs/POSTGRES-CONFIGURATION.md +630 -0
  58. package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +1317 -0
  59. package/infrastructure/docs/WEBSOCKET-CONFIGURATION.md +105 -0
  60. package/infrastructure/docs/deployment-instructions.md +268 -0
  61. package/infrastructure/docs/generate-iam-command.md +278 -0
  62. package/infrastructure/docs/iam-policy-templates.md +193 -0
  63. package/infrastructure/domains/database/aurora-builder.js +809 -0
  64. package/infrastructure/domains/database/aurora-builder.test.js +950 -0
  65. package/infrastructure/domains/database/aurora-discovery.js +87 -0
  66. package/infrastructure/domains/database/aurora-discovery.test.js +188 -0
  67. package/infrastructure/domains/database/aurora-resolver.js +210 -0
  68. package/infrastructure/domains/database/aurora-resolver.test.js +347 -0
  69. package/infrastructure/domains/database/migration-builder.js +701 -0
  70. package/infrastructure/domains/database/migration-builder.test.js +321 -0
  71. package/infrastructure/domains/database/migration-resolver.js +163 -0
  72. package/infrastructure/domains/database/migration-resolver.test.js +337 -0
  73. package/infrastructure/domains/health/application/ports/IPropertyReconciler.js +164 -0
  74. package/infrastructure/domains/health/application/ports/IResourceDetector.js +129 -0
  75. package/infrastructure/domains/health/application/ports/IResourceImporter.js +142 -0
  76. package/infrastructure/domains/health/application/ports/IStackRepository.js +131 -0
  77. package/infrastructure/domains/health/application/ports/index.js +26 -0
  78. package/infrastructure/domains/health/application/use-cases/__tests__/execute-resource-import-use-case.test.js +679 -0
  79. package/infrastructure/domains/health/application/use-cases/__tests__/mismatch-analyzer-method-name.test.js +167 -0
  80. package/infrastructure/domains/health/application/use-cases/__tests__/repair-via-import-use-case.test.js +1130 -0
  81. package/infrastructure/domains/health/application/use-cases/execute-resource-import-use-case.js +221 -0
  82. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.js +152 -0
  83. package/infrastructure/domains/health/application/use-cases/reconcile-properties-use-case.test.js +343 -0
  84. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.js +535 -0
  85. package/infrastructure/domains/health/application/use-cases/repair-via-import-use-case.test.js +376 -0
  86. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.js +213 -0
  87. package/infrastructure/domains/health/application/use-cases/run-health-check-use-case.test.js +441 -0
  88. package/infrastructure/domains/health/docs/ACME-DEV-DRIFT-ANALYSIS.md +267 -0
  89. package/infrastructure/domains/health/docs/BUILD-VS-DEPLOYED-TEMPLATE-ANALYSIS.md +324 -0
  90. package/infrastructure/domains/health/docs/ORPHAN-DETECTION-ANALYSIS.md +386 -0
  91. package/infrastructure/domains/health/docs/SPEC-CLEANUP-COMMAND.md +1419 -0
  92. package/infrastructure/domains/health/docs/TDD-IMPLEMENTATION-SUMMARY.md +391 -0
  93. package/infrastructure/domains/health/docs/TEMPLATE-COMPARISON-IMPLEMENTATION.md +551 -0
  94. package/infrastructure/domains/health/domain/entities/issue.js +299 -0
  95. package/infrastructure/domains/health/domain/entities/issue.test.js +528 -0
  96. package/infrastructure/domains/health/domain/entities/property-mismatch.js +108 -0
  97. package/infrastructure/domains/health/domain/entities/property-mismatch.test.js +275 -0
  98. package/infrastructure/domains/health/domain/entities/resource.js +159 -0
  99. package/infrastructure/domains/health/domain/entities/resource.test.js +432 -0
  100. package/infrastructure/domains/health/domain/entities/stack-health-report.js +306 -0
  101. package/infrastructure/domains/health/domain/entities/stack-health-report.test.js +601 -0
  102. package/infrastructure/domains/health/domain/services/__tests__/health-score-percentage-based.test.js +380 -0
  103. package/infrastructure/domains/health/domain/services/__tests__/import-progress-monitor.test.js +971 -0
  104. package/infrastructure/domains/health/domain/services/__tests__/import-template-generator.test.js +1150 -0
  105. package/infrastructure/domains/health/domain/services/__tests__/logical-id-mapper.test.js +672 -0
  106. package/infrastructure/domains/health/domain/services/__tests__/template-parser.test.js +496 -0
  107. package/infrastructure/domains/health/domain/services/__tests__/update-progress-monitor.test.js +419 -0
  108. package/infrastructure/domains/health/domain/services/health-score-calculator.js +248 -0
  109. package/infrastructure/domains/health/domain/services/health-score-calculator.test.js +504 -0
  110. package/infrastructure/domains/health/domain/services/import-progress-monitor.js +195 -0
  111. package/infrastructure/domains/health/domain/services/import-template-generator.js +435 -0
  112. package/infrastructure/domains/health/domain/services/logical-id-mapper.js +345 -0
  113. package/infrastructure/domains/health/domain/services/mismatch-analyzer.js +234 -0
  114. package/infrastructure/domains/health/domain/services/mismatch-analyzer.test.js +431 -0
  115. package/infrastructure/domains/health/domain/services/property-mutability-config.js +382 -0
  116. package/infrastructure/domains/health/domain/services/template-parser.js +245 -0
  117. package/infrastructure/domains/health/domain/services/update-progress-monitor.js +192 -0
  118. package/infrastructure/domains/health/domain/value-objects/health-score.js +138 -0
  119. package/infrastructure/domains/health/domain/value-objects/health-score.test.js +267 -0
  120. package/infrastructure/domains/health/domain/value-objects/property-mutability.js +161 -0
  121. package/infrastructure/domains/health/domain/value-objects/property-mutability.test.js +198 -0
  122. package/infrastructure/domains/health/domain/value-objects/resource-state.js +167 -0
  123. package/infrastructure/domains/health/domain/value-objects/resource-state.test.js +196 -0
  124. package/infrastructure/domains/health/domain/value-objects/stack-identifier.js +192 -0
  125. package/infrastructure/domains/health/domain/value-objects/stack-identifier.test.js +262 -0
  126. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-cfn-tagged.test.js +312 -0
  127. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-multi-stack.test.js +367 -0
  128. package/infrastructure/domains/health/infrastructure/adapters/__tests__/orphan-detection-relationship-analysis.test.js +432 -0
  129. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.js +784 -0
  130. package/infrastructure/domains/health/infrastructure/adapters/aws-property-reconciler.test.js +1133 -0
  131. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.js +565 -0
  132. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-detector.test.js +554 -0
  133. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.js +318 -0
  134. package/infrastructure/domains/health/infrastructure/adapters/aws-resource-importer.test.js +398 -0
  135. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.js +777 -0
  136. package/infrastructure/domains/health/infrastructure/adapters/aws-stack-repository.test.js +580 -0
  137. package/infrastructure/domains/integration/integration-builder.js +404 -0
  138. package/infrastructure/domains/integration/integration-builder.test.js +690 -0
  139. package/infrastructure/domains/integration/integration-resolver.js +170 -0
  140. package/infrastructure/domains/integration/integration-resolver.test.js +369 -0
  141. package/infrastructure/domains/integration/websocket-builder.js +69 -0
  142. package/infrastructure/domains/integration/websocket-builder.test.js +195 -0
  143. package/infrastructure/domains/networking/vpc-builder.js +2051 -0
  144. package/infrastructure/domains/networking/vpc-builder.test.js +1960 -0
  145. package/infrastructure/domains/networking/vpc-discovery.js +177 -0
  146. package/infrastructure/domains/networking/vpc-discovery.test.js +350 -0
  147. package/infrastructure/domains/networking/vpc-resolver.js +505 -0
  148. package/infrastructure/domains/networking/vpc-resolver.test.js +801 -0
  149. package/infrastructure/domains/parameters/ssm-builder.js +79 -0
  150. package/infrastructure/domains/parameters/ssm-builder.test.js +189 -0
  151. package/infrastructure/domains/parameters/ssm-discovery.js +84 -0
  152. package/infrastructure/domains/parameters/ssm-discovery.test.js +210 -0
  153. package/infrastructure/domains/security/iam-generator.js +816 -0
  154. package/infrastructure/domains/security/iam-generator.test.js +204 -0
  155. package/infrastructure/domains/security/kms-builder.js +415 -0
  156. package/infrastructure/domains/security/kms-builder.test.js +392 -0
  157. package/infrastructure/domains/security/kms-discovery.js +80 -0
  158. package/infrastructure/domains/security/kms-discovery.test.js +177 -0
  159. package/infrastructure/domains/security/kms-resolver.js +96 -0
  160. package/infrastructure/domains/security/kms-resolver.test.js +216 -0
  161. package/infrastructure/domains/security/templates/frigg-deployment-iam-stack.yaml +401 -0
  162. package/infrastructure/domains/security/templates/iam-policy-basic.json +218 -0
  163. package/infrastructure/domains/security/templates/iam-policy-full.json +288 -0
  164. package/infrastructure/domains/shared/base-builder.js +112 -0
  165. package/infrastructure/domains/shared/base-resolver.js +186 -0
  166. package/infrastructure/domains/shared/base-resolver.test.js +305 -0
  167. package/infrastructure/domains/shared/builder-orchestrator.js +212 -0
  168. package/infrastructure/domains/shared/builder-orchestrator.test.js +213 -0
  169. package/infrastructure/domains/shared/cloudformation-discovery-v2.js +334 -0
  170. package/infrastructure/domains/shared/cloudformation-discovery.js +672 -0
  171. package/infrastructure/domains/shared/cloudformation-discovery.test.js +985 -0
  172. package/infrastructure/domains/shared/environment-builder.js +119 -0
  173. package/infrastructure/domains/shared/environment-builder.test.js +247 -0
  174. package/infrastructure/domains/shared/providers/aws-provider-adapter.js +579 -0
  175. package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +416 -0
  176. package/infrastructure/domains/shared/providers/azure-provider-adapter.stub.js +93 -0
  177. package/infrastructure/domains/shared/providers/cloud-provider-adapter.js +136 -0
  178. package/infrastructure/domains/shared/providers/gcp-provider-adapter.stub.js +82 -0
  179. package/infrastructure/domains/shared/providers/provider-factory.js +108 -0
  180. package/infrastructure/domains/shared/providers/provider-factory.test.js +170 -0
  181. package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +306 -0
  182. package/infrastructure/domains/shared/resource-discovery.js +233 -0
  183. package/infrastructure/domains/shared/resource-discovery.test.js +588 -0
  184. package/infrastructure/domains/shared/types/app-definition.js +205 -0
  185. package/infrastructure/domains/shared/types/discovery-result.js +106 -0
  186. package/infrastructure/domains/shared/types/discovery-result.test.js +258 -0
  187. package/infrastructure/domains/shared/types/index.js +46 -0
  188. package/infrastructure/domains/shared/types/resource-ownership.js +108 -0
  189. package/infrastructure/domains/shared/types/resource-ownership.test.js +101 -0
  190. package/infrastructure/domains/shared/utilities/base-definition-factory.js +394 -0
  191. package/infrastructure/domains/shared/utilities/base-definition-factory.js.bak +338 -0
  192. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +291 -0
  193. package/infrastructure/domains/shared/utilities/handler-path-resolver.js +134 -0
  194. package/infrastructure/domains/shared/utilities/handler-path-resolver.test.js +268 -0
  195. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +159 -0
  196. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +444 -0
  197. package/infrastructure/domains/shared/validation/env-validator.js +78 -0
  198. package/infrastructure/domains/shared/validation/env-validator.test.js +173 -0
  199. package/infrastructure/domains/shared/validation/plugin-validator.js +187 -0
  200. package/infrastructure/domains/shared/validation/plugin-validator.test.js +323 -0
  201. package/infrastructure/esbuild.config.js +53 -0
  202. package/infrastructure/infrastructure-composer.js +117 -0
  203. package/infrastructure/infrastructure-composer.test.js +1895 -0
  204. package/infrastructure/integration.test.js +383 -0
  205. package/infrastructure/scripts/build-prisma-layer.js +701 -0
  206. package/infrastructure/scripts/build-prisma-layer.test.js +170 -0
  207. package/infrastructure/scripts/build-time-discovery.js +238 -0
  208. package/infrastructure/scripts/build-time-discovery.test.js +379 -0
  209. package/infrastructure/scripts/run-discovery.js +110 -0
  210. package/infrastructure/scripts/verify-prisma-layer.js +72 -0
  211. package/layers/prisma/.build-complete +3 -0
  212. package/layers/prisma/nodejs/package.json +8 -0
  213. package/management-ui/.eslintrc.js +22 -0
  214. package/management-ui/README.md +203 -0
  215. package/management-ui/components.json +21 -0
  216. package/management-ui/docs/phase2-integration-guide.md +320 -0
  217. package/management-ui/index.html +13 -0
  218. package/management-ui/package.json +76 -0
  219. package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
  220. package/management-ui/postcss.config.js +6 -0
  221. package/management-ui/server/api/backend.js +256 -0
  222. package/management-ui/server/api/cli.js +315 -0
  223. package/management-ui/server/api/codegen.js +663 -0
  224. package/management-ui/server/api/connections.js +857 -0
  225. package/management-ui/server/api/discovery.js +185 -0
  226. package/management-ui/server/api/environment/index.js +1 -0
  227. package/management-ui/server/api/environment/router.js +378 -0
  228. package/management-ui/server/api/environment.js +328 -0
  229. package/management-ui/server/api/integrations.js +876 -0
  230. package/management-ui/server/api/logs.js +248 -0
  231. package/management-ui/server/api/monitoring.js +282 -0
  232. package/management-ui/server/api/open-ide.js +31 -0
  233. package/management-ui/server/api/project.js +1029 -0
  234. package/management-ui/server/api/users/sessions.js +371 -0
  235. package/management-ui/server/api/users/simulation.js +254 -0
  236. package/management-ui/server/api/users.js +362 -0
  237. package/management-ui/server/api-contract.md +275 -0
  238. package/management-ui/server/index.js +873 -0
  239. package/management-ui/server/middleware/errorHandler.js +93 -0
  240. package/management-ui/server/middleware/security.js +32 -0
  241. package/management-ui/server/processManager.js +296 -0
  242. package/management-ui/server/server.js +346 -0
  243. package/management-ui/server/services/aws-monitor.js +413 -0
  244. package/management-ui/server/services/npm-registry.js +347 -0
  245. package/management-ui/server/services/template-engine.js +538 -0
  246. package/management-ui/server/utils/cliIntegration.js +220 -0
  247. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  248. package/management-ui/server/utils/environment/awsParameterStore.js +275 -0
  249. package/management-ui/server/utils/environment/encryption.js +278 -0
  250. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  251. package/management-ui/server/utils/import-commonjs.js +28 -0
  252. package/management-ui/server/utils/response.js +83 -0
  253. package/management-ui/server/websocket/handler.js +325 -0
  254. package/management-ui/src/App.jsx +25 -0
  255. package/management-ui/src/assets/FriggLogo.svg +1 -0
  256. package/management-ui/src/components/AppRouter.jsx +65 -0
  257. package/management-ui/src/components/Button.jsx +70 -0
  258. package/management-ui/src/components/Card.jsx +97 -0
  259. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  260. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  261. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  262. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  263. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  264. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  265. package/management-ui/src/components/IntegrationCard.jsx +481 -0
  266. package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
  267. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  268. package/management-ui/src/components/IntegrationStatus.jsx +336 -0
  269. package/management-ui/src/components/Layout.jsx +716 -0
  270. package/management-ui/src/components/LoadingSpinner.jsx +113 -0
  271. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  272. package/management-ui/src/components/SessionMonitor.jsx +350 -0
  273. package/management-ui/src/components/StatusBadge.jsx +208 -0
  274. package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
  275. package/management-ui/src/components/UserSimulation.jsx +327 -0
  276. package/management-ui/src/components/Welcome.jsx +434 -0
  277. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  278. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  279. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  280. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  281. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  282. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  283. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  284. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  285. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  286. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  287. package/management-ui/src/components/codegen/index.js +10 -0
  288. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  289. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  290. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  291. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  292. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  293. package/management-ui/src/components/connections/index.js +5 -0
  294. package/management-ui/src/components/index.js +21 -0
  295. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  296. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  297. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  298. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  299. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  300. package/management-ui/src/components/monitoring/index.js +6 -0
  301. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  302. package/management-ui/src/components/theme-provider.jsx +52 -0
  303. package/management-ui/src/components/theme-toggle.jsx +39 -0
  304. package/management-ui/src/components/ui/badge.tsx +36 -0
  305. package/management-ui/src/components/ui/button.test.jsx +56 -0
  306. package/management-ui/src/components/ui/button.tsx +57 -0
  307. package/management-ui/src/components/ui/card.tsx +76 -0
  308. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  309. package/management-ui/src/components/ui/select.tsx +157 -0
  310. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  311. package/management-ui/src/hooks/useFrigg.jsx +387 -0
  312. package/management-ui/src/hooks/useSocket.jsx +58 -0
  313. package/management-ui/src/index.css +193 -0
  314. package/management-ui/src/lib/utils.ts +6 -0
  315. package/management-ui/src/main.jsx +10 -0
  316. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  317. package/management-ui/src/pages/Connections.jsx +252 -0
  318. package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
  319. package/management-ui/src/pages/Dashboard.jsx +311 -0
  320. package/management-ui/src/pages/Environment.jsx +314 -0
  321. package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
  322. package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
  323. package/management-ui/src/pages/IntegrationTest.jsx +742 -0
  324. package/management-ui/src/pages/Integrations.jsx +253 -0
  325. package/management-ui/src/pages/Monitoring.jsx +17 -0
  326. package/management-ui/src/pages/Simulation.jsx +155 -0
  327. package/management-ui/src/pages/Users.jsx +492 -0
  328. package/management-ui/src/services/api.js +41 -0
  329. package/management-ui/src/services/apiModuleService.js +193 -0
  330. package/management-ui/src/services/websocket-handlers.js +120 -0
  331. package/management-ui/src/test/api/project.test.js +273 -0
  332. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  333. package/management-ui/src/test/mocks/server.js +178 -0
  334. package/management-ui/src/test/setup.js +61 -0
  335. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  336. package/management-ui/src/utils/repository.js +98 -0
  337. package/management-ui/src/utils/repository.test.js +118 -0
  338. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  339. package/management-ui/tailwind.config.js +63 -0
  340. package/management-ui/tsconfig.json +37 -0
  341. package/management-ui/tsconfig.node.json +10 -0
  342. package/management-ui/vite.config.js +26 -0
  343. package/management-ui/vitest.config.js +38 -0
  344. package/package.json +35 -14
  345. package/test/index.js +2 -4
  346. package/test/mock-integration.js +4 -14
  347. package/infrastructure/app-handler-helpers.js +0 -57
  348. package/infrastructure/backend-utils.js +0 -87
  349. package/infrastructure/routers/auth.js +0 -26
  350. package/infrastructure/routers/integration-defined-routers.js +0 -42
  351. package/infrastructure/routers/middleware/loadUser.js +0 -15
  352. package/infrastructure/routers/middleware/requireLoggedInUser.js +0 -12
  353. package/infrastructure/routers/user.js +0 -41
  354. package/infrastructure/routers/websocket.js +0 -55
  355. package/infrastructure/serverless-template.js +0 -291
  356. package/infrastructure/workers/integration-defined-workers.js +0 -24
  357. package/test/auther-definition-tester.js +0 -125
@@ -0,0 +1,637 @@
1
+ import React, { useState, useCallback } from 'react';
2
+ import { Card } from '../Card';
3
+ import { Button } from '../Button';
4
+ import SchemaBuilder from './SchemaBuilder';
5
+
6
+ const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];
7
+
8
+ const RESPONSE_TYPES = [
9
+ { value: 'json', label: 'JSON Object' },
10
+ { value: 'array', label: 'JSON Array' },
11
+ { value: 'string', label: 'String' },
12
+ { value: 'number', label: 'Number' },
13
+ { value: 'boolean', label: 'Boolean' },
14
+ { value: 'file', label: 'File/Binary' }
15
+ ];
16
+
17
+ const APIEndpointGenerator = ({ onGenerate }) => {
18
+ const [endpoints, setEndpoints] = useState([]);
19
+ const [currentEndpoint, setCurrentEndpoint] = useState(null);
20
+ const [apiInfo, setApiInfo] = useState({
21
+ name: '',
22
+ description: '',
23
+ baseURL: '',
24
+ version: '1.0.0',
25
+ authentication: 'bearer'
26
+ });
27
+
28
+ const createNewEndpoint = useCallback(() => {
29
+ const newEndpoint = {
30
+ id: Date.now(),
31
+ path: '',
32
+ method: 'GET',
33
+ summary: '',
34
+ description: '',
35
+ tags: [],
36
+ parameters: [],
37
+ requestBody: null,
38
+ responses: {
39
+ 200: { description: 'Success', schema: [] }
40
+ },
41
+ security: true
42
+ };
43
+ setEndpoints(prev => [...prev, newEndpoint]);
44
+ setCurrentEndpoint(newEndpoint.id);
45
+ }, []);
46
+
47
+ const updateEndpoint = useCallback((id, updates) => {
48
+ setEndpoints(prev => prev.map(endpoint =>
49
+ endpoint.id === id ? { ...endpoint, ...updates } : endpoint
50
+ ));
51
+ }, []);
52
+
53
+ const removeEndpoint = useCallback((id) => {
54
+ setEndpoints(prev => prev.filter(endpoint => endpoint.id !== id));
55
+ if (currentEndpoint === id) {
56
+ setCurrentEndpoint(null);
57
+ }
58
+ }, [currentEndpoint]);
59
+
60
+ const addParameter = useCallback((endpointId) => {
61
+ const newParam = {
62
+ id: Date.now(),
63
+ name: '',
64
+ in: 'query',
65
+ type: 'string',
66
+ required: false,
67
+ description: ''
68
+ };
69
+
70
+ updateEndpoint(endpointId, {
71
+ parameters: [...(endpoints.find(e => e.id === endpointId)?.parameters || []), newParam]
72
+ });
73
+ }, [endpoints, updateEndpoint]);
74
+
75
+ const updateParameter = useCallback((endpointId, paramId, updates) => {
76
+ const endpoint = endpoints.find(e => e.id === endpointId);
77
+ if (!endpoint) return;
78
+
79
+ const updatedParams = endpoint.parameters.map(param =>
80
+ param.id === paramId ? { ...param, ...updates } : param
81
+ );
82
+
83
+ updateEndpoint(endpointId, { parameters: updatedParams });
84
+ }, [endpoints, updateEndpoint]);
85
+
86
+ const removeParameter = useCallback((endpointId, paramId) => {
87
+ const endpoint = endpoints.find(e => e.id === endpointId);
88
+ if (!endpoint) return;
89
+
90
+ const updatedParams = endpoint.parameters.filter(param => param.id !== paramId);
91
+ updateEndpoint(endpointId, { parameters: updatedParams });
92
+ }, [endpoints, updateEndpoint]);
93
+
94
+ const generateRouterCode = useCallback(() => {
95
+ const routerName = apiInfo.name.replace(/[^a-zA-Z0-9]/g, '').toLowerCase();
96
+
97
+ const imports = `const express = require('express');
98
+ const router = express.Router();
99
+ const { validateRequest, handleError } = require('../middleware');
100
+ const { ${apiInfo.name}Service } = require('../services');`;
101
+
102
+ const routes = endpoints.map(endpoint => {
103
+ const methodName = endpoint.path.replace(/[^a-zA-Z0-9]/g, '').toLowerCase() + endpoint.method.toLowerCase();
104
+ const expressPath = endpoint.path.replace(/{([^}]+)}/g, ':$1');
105
+
106
+ const validationMiddleware = endpoint.parameters.length > 0 ? `validateRequest(${JSON.stringify(endpoint.parameters)}), ` : '';
107
+ const authMiddleware = endpoint.security ? 'requireAuth, ' : '';
108
+
109
+ return `// ${endpoint.summary || endpoint.description || 'No description'}
110
+ router.${endpoint.method.toLowerCase()}('${expressPath}', ${authMiddleware}${validationMiddleware}async (req, res) => {
111
+ try {
112
+ ${generateRouteBody(endpoint)}
113
+ res.json(result);
114
+ } catch (error) {
115
+ handleError(error, res);
116
+ }
117
+ });`;
118
+ }).join('\n\n');
119
+
120
+ const exports = `module.exports = router;`;
121
+
122
+ return `${imports}
123
+
124
+ ${routes}
125
+
126
+ ${exports}`;
127
+ }, [apiInfo, endpoints]);
128
+
129
+ const generateRouteBody = (endpoint) => {
130
+ const params = endpoint.parameters.filter(p => p.in === 'path').map(p => `req.params.${p.name}`);
131
+ const query = endpoint.parameters.filter(p => p.in === 'query').length > 0 ? 'req.query' : null;
132
+ const body = endpoint.requestBody ? 'req.body' : null;
133
+
134
+ const args = [params, query, body].filter(Boolean).flat();
135
+ const methodName = endpoint.path.replace(/[^a-zA-Z0-9]/g, '').toLowerCase() + endpoint.method.toLowerCase();
136
+
137
+ return ` const result = await ${apiInfo.name}Service.${methodName}(${args.join(', ')});`;
138
+ };
139
+
140
+ const generateOpenAPISpec = useCallback(() => {
141
+ const spec = {
142
+ openapi: '3.0.0',
143
+ info: {
144
+ title: apiInfo.name,
145
+ description: apiInfo.description,
146
+ version: apiInfo.version
147
+ },
148
+ servers: [
149
+ {
150
+ url: apiInfo.baseURL,
151
+ description: 'API Server'
152
+ }
153
+ ],
154
+ paths: {},
155
+ components: {
156
+ securitySchemes: {
157
+ bearerAuth: {
158
+ type: 'http',
159
+ scheme: 'bearer',
160
+ bearerFormat: 'JWT'
161
+ }
162
+ }
163
+ }
164
+ };
165
+
166
+ endpoints.forEach(endpoint => {
167
+ if (!spec.paths[endpoint.path]) {
168
+ spec.paths[endpoint.path] = {};
169
+ }
170
+
171
+ spec.paths[endpoint.path][endpoint.method.toLowerCase()] = {
172
+ summary: endpoint.summary,
173
+ description: endpoint.description,
174
+ tags: endpoint.tags,
175
+ parameters: endpoint.parameters.map(param => ({
176
+ name: param.name,
177
+ in: param.in,
178
+ required: param.required,
179
+ description: param.description,
180
+ schema: { type: param.type }
181
+ })),
182
+ responses: Object.entries(endpoint.responses).reduce((acc, [code, response]) => {
183
+ acc[code] = {
184
+ description: response.description,
185
+ content: {
186
+ 'application/json': {
187
+ schema: generateJsonSchema(response.schema)
188
+ }
189
+ }
190
+ };
191
+ return acc;
192
+ }, {}),
193
+ ...(endpoint.security ? { security: [{ bearerAuth: [] }] } : {})
194
+ };
195
+
196
+ if (endpoint.requestBody) {
197
+ spec.paths[endpoint.path][endpoint.method.toLowerCase()].requestBody = {
198
+ required: true,
199
+ content: {
200
+ 'application/json': {
201
+ schema: generateJsonSchema(endpoint.requestBody.schema)
202
+ }
203
+ }
204
+ };
205
+ }
206
+ });
207
+
208
+ return JSON.stringify(spec, null, 2);
209
+ }, [apiInfo, endpoints]);
210
+
211
+ const generateJsonSchema = (schemaFields) => {
212
+ if (!schemaFields || schemaFields.length === 0) {
213
+ return { type: 'object' };
214
+ }
215
+
216
+ const properties = {};
217
+ const required = [];
218
+
219
+ schemaFields.forEach(field => {
220
+ properties[field.name] = {
221
+ type: field.type,
222
+ description: field.label || field.name
223
+ };
224
+
225
+ if (field.required) {
226
+ required.push(field.name);
227
+ }
228
+
229
+ if (field.validation) {
230
+ Object.assign(properties[field.name], field.validation);
231
+ }
232
+ });
233
+
234
+ return {
235
+ type: 'object',
236
+ properties,
237
+ required
238
+ };
239
+ };
240
+
241
+ const generateServiceCode = useCallback(() => {
242
+ const serviceName = apiInfo.name + 'Service';
243
+
244
+ const methods = endpoints.map(endpoint => {
245
+ const methodName = endpoint.path.replace(/[^a-zA-Z0-9]/g, '').toLowerCase() + endpoint.method.toLowerCase();
246
+ const params = endpoint.parameters.filter(p => p.in === 'path').map(p => p.name);
247
+ const queryParams = endpoint.parameters.filter(p => p.in === 'query').length > 0;
248
+ const hasBody = endpoint.requestBody;
249
+
250
+ const args = [];
251
+ if (params.length > 0) args.push(params.join(', '));
252
+ if (queryParams) args.push('query');
253
+ if (hasBody) args.push('data');
254
+
255
+ return ` static async ${methodName}(${args.join(', ')}) {
256
+ // TODO: Implement ${endpoint.summary || endpoint.description || 'endpoint logic'}
257
+ throw new Error('Not implemented');
258
+ }`;
259
+ }).join('\n\n');
260
+
261
+ return `class ${serviceName} {
262
+ ${methods}
263
+ }
264
+
265
+ module.exports = ${serviceName};`;
266
+ }, [apiInfo, endpoints]);
267
+
268
+ const handleGenerate = useCallback(() => {
269
+ const routerCode = generateRouterCode();
270
+ const serviceCode = generateServiceCode();
271
+ const openApiSpec = generateOpenAPISpec();
272
+
273
+ const metadata = {
274
+ name: apiInfo.name,
275
+ type: 'api-endpoints',
276
+ files: [
277
+ { name: 'router.js', content: routerCode },
278
+ { name: 'service.js', content: serviceCode },
279
+ { name: 'openapi.json', content: openApiSpec },
280
+ { name: 'README.md', content: generateReadme() }
281
+ ]
282
+ };
283
+
284
+ onGenerate(apiInfo, { router: routerCode, service: serviceCode, openapi: openApiSpec }, metadata);
285
+ }, [apiInfo, generateRouterCode, generateServiceCode, generateOpenAPISpec, onGenerate]);
286
+
287
+ const generateReadme = () => {
288
+ return `# ${apiInfo.name} API
289
+
290
+ ${apiInfo.description}
291
+
292
+ ## Endpoints
293
+
294
+ ${endpoints.map(endpoint => `### ${endpoint.method} ${endpoint.path}
295
+
296
+ ${endpoint.description || endpoint.summary || 'No description available'}
297
+
298
+ ${endpoint.parameters.length > 0 ? `**Parameters:**
299
+ ${endpoint.parameters.map(p => `- \`${p.name}\` (${p.type}${p.required ? ', required' : ''}): ${p.description || 'No description'}`).join('\n')}` : ''}
300
+ `).join('\n')}
301
+
302
+ ## Authentication
303
+
304
+ ${apiInfo.authentication === 'bearer' ? 'This API uses Bearer token authentication.' : 'Authentication method not specified.'}
305
+
306
+ ## Usage
307
+
308
+ 1. Import the router in your Express app
309
+ 2. Mount the router at your desired path
310
+ 3. Implement the service methods
311
+ 4. Test the endpoints
312
+
313
+ \`\`\`javascript
314
+ const app = require('express')();
315
+ const ${apiInfo.name.toLowerCase()}Router = require('./router');
316
+
317
+ app.use('/api/${apiInfo.name.toLowerCase()}', ${apiInfo.name.toLowerCase()}Router);
318
+ \`\`\`
319
+ `;
320
+ };
321
+
322
+ const selectedEndpoint = endpoints.find(e => e.id === currentEndpoint);
323
+
324
+ return (
325
+ <div className="space-y-6">
326
+ <h2 className="text-2xl font-bold">API Endpoint Generator</h2>
327
+
328
+ {/* API Info */}
329
+ <Card className="p-6">
330
+ <h3 className="text-lg font-medium mb-4">API Information</h3>
331
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
332
+ <div>
333
+ <label className="block text-sm font-medium text-gray-700 mb-2">API Name *</label>
334
+ <input
335
+ type="text"
336
+ value={apiInfo.name}
337
+ onChange={(e) => setApiInfo(prev => ({ ...prev, name: e.target.value }))}
338
+ placeholder="UserAPI"
339
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
340
+ />
341
+ </div>
342
+ <div>
343
+ <label className="block text-sm font-medium text-gray-700 mb-2">Version</label>
344
+ <input
345
+ type="text"
346
+ value={apiInfo.version}
347
+ onChange={(e) => setApiInfo(prev => ({ ...prev, version: e.target.value }))}
348
+ placeholder="1.0.0"
349
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
350
+ />
351
+ </div>
352
+ <div className="md:col-span-2">
353
+ <label className="block text-sm font-medium text-gray-700 mb-2">Description</label>
354
+ <textarea
355
+ value={apiInfo.description}
356
+ onChange={(e) => setApiInfo(prev => ({ ...prev, description: e.target.value }))}
357
+ placeholder="API description"
358
+ rows={2}
359
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
360
+ />
361
+ </div>
362
+ <div>
363
+ <label className="block text-sm font-medium text-gray-700 mb-2">Base URL</label>
364
+ <input
365
+ type="url"
366
+ value={apiInfo.baseURL}
367
+ onChange={(e) => setApiInfo(prev => ({ ...prev, baseURL: e.target.value }))}
368
+ placeholder="https://api.example.com"
369
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
370
+ />
371
+ </div>
372
+ <div>
373
+ <label className="block text-sm font-medium text-gray-700 mb-2">Authentication</label>
374
+ <select
375
+ value={apiInfo.authentication}
376
+ onChange={(e) => setApiInfo(prev => ({ ...prev, authentication: e.target.value }))}
377
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
378
+ >
379
+ <option value="bearer">Bearer Token</option>
380
+ <option value="api-key">API Key</option>
381
+ <option value="basic">Basic Auth</option>
382
+ <option value="none">None</option>
383
+ </select>
384
+ </div>
385
+ </div>
386
+ </Card>
387
+
388
+ {/* Endpoints List */}
389
+ <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
390
+ <div className="lg:col-span-1">
391
+ <Card className="p-4">
392
+ <div className="flex justify-between items-center mb-4">
393
+ <h3 className="text-lg font-medium">Endpoints</h3>
394
+ <Button onClick={createNewEndpoint} size="sm">Add</Button>
395
+ </div>
396
+
397
+ {endpoints.length === 0 && (
398
+ <div className="text-center py-4 text-gray-500">
399
+ No endpoints yet. Click "Add" to create one.
400
+ </div>
401
+ )}
402
+
403
+ <div className="space-y-2">
404
+ {endpoints.map(endpoint => (
405
+ <div
406
+ key={endpoint.id}
407
+ onClick={() => setCurrentEndpoint(endpoint.id)}
408
+ className={`p-3 rounded border cursor-pointer transition-colors ${
409
+ currentEndpoint === endpoint.id
410
+ ? 'border-blue-500 bg-blue-50'
411
+ : 'border-gray-200 hover:border-gray-300'
412
+ }`}
413
+ >
414
+ <div className="flex items-center justify-between">
415
+ <div>
416
+ <span className={`inline-block px-2 py-1 text-xs rounded font-medium ${
417
+ endpoint.method === 'GET' ? 'bg-green-100 text-green-800' :
418
+ endpoint.method === 'POST' ? 'bg-blue-100 text-blue-800' :
419
+ endpoint.method === 'PUT' ? 'bg-yellow-100 text-yellow-800' :
420
+ endpoint.method === 'DELETE' ? 'bg-red-100 text-red-800' :
421
+ 'bg-gray-100 text-gray-800'
422
+ }`}>
423
+ {endpoint.method}
424
+ </span>
425
+ <div className="text-sm font-medium mt-1">
426
+ {endpoint.path || '/path'}
427
+ </div>
428
+ {endpoint.summary && (
429
+ <div className="text-xs text-gray-500 mt-1">
430
+ {endpoint.summary}
431
+ </div>
432
+ )}
433
+ </div>
434
+ <Button
435
+ size="sm"
436
+ variant="outline"
437
+ onClick={(e) => {
438
+ e.stopPropagation();
439
+ removeEndpoint(endpoint.id);
440
+ }}
441
+ className="text-red-600 hover:text-red-700"
442
+ >
443
+ ×
444
+ </Button>
445
+ </div>
446
+ </div>
447
+ ))}
448
+ </div>
449
+ </Card>
450
+ </div>
451
+
452
+ {/* Endpoint Editor */}
453
+ <div className="lg:col-span-2">
454
+ {selectedEndpoint ? (
455
+ <Card className="p-6">
456
+ <h3 className="text-lg font-medium mb-4">Edit Endpoint</h3>
457
+
458
+ <div className="space-y-4">
459
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
460
+ <div>
461
+ <label className="block text-sm font-medium text-gray-700 mb-2">Method</label>
462
+ <select
463
+ value={selectedEndpoint.method}
464
+ onChange={(e) => updateEndpoint(selectedEndpoint.id, { method: e.target.value })}
465
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
466
+ >
467
+ {HTTP_METHODS.map(method => (
468
+ <option key={method} value={method}>{method}</option>
469
+ ))}
470
+ </select>
471
+ </div>
472
+ <div className="md:col-span-2">
473
+ <label className="block text-sm font-medium text-gray-700 mb-2">Path</label>
474
+ <input
475
+ type="text"
476
+ value={selectedEndpoint.path}
477
+ onChange={(e) => updateEndpoint(selectedEndpoint.id, { path: e.target.value })}
478
+ placeholder="/users/{id}"
479
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
480
+ />
481
+ </div>
482
+ </div>
483
+
484
+ <div>
485
+ <label className="block text-sm font-medium text-gray-700 mb-2">Summary</label>
486
+ <input
487
+ type="text"
488
+ value={selectedEndpoint.summary}
489
+ onChange={(e) => updateEndpoint(selectedEndpoint.id, { summary: e.target.value })}
490
+ placeholder="Brief summary"
491
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
492
+ />
493
+ </div>
494
+
495
+ <div>
496
+ <label className="block text-sm font-medium text-gray-700 mb-2">Description</label>
497
+ <textarea
498
+ value={selectedEndpoint.description}
499
+ onChange={(e) => updateEndpoint(selectedEndpoint.id, { description: e.target.value })}
500
+ placeholder="Detailed description"
501
+ rows={3}
502
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
503
+ />
504
+ </div>
505
+
506
+ <div className="flex items-center">
507
+ <input
508
+ type="checkbox"
509
+ id={`security-${selectedEndpoint.id}`}
510
+ checked={selectedEndpoint.security}
511
+ onChange={(e) => updateEndpoint(selectedEndpoint.id, { security: e.target.checked })}
512
+ className="mr-2"
513
+ />
514
+ <label htmlFor={`security-${selectedEndpoint.id}`} className="text-sm">
515
+ Requires Authentication
516
+ </label>
517
+ </div>
518
+
519
+ {/* Parameters */}
520
+ <div>
521
+ <div className="flex justify-between items-center mb-3">
522
+ <h4 className="font-medium">Parameters</h4>
523
+ <Button
524
+ size="sm"
525
+ onClick={() => addParameter(selectedEndpoint.id)}
526
+ >
527
+ Add Parameter
528
+ </Button>
529
+ </div>
530
+
531
+ {selectedEndpoint.parameters?.length === 0 && (
532
+ <div className="text-sm text-gray-500 py-2">No parameters defined</div>
533
+ )}
534
+
535
+ {selectedEndpoint.parameters?.map(param => (
536
+ <div key={param.id} className="border rounded p-3 mb-2">
537
+ <div className="grid grid-cols-1 md:grid-cols-4 gap-2 mb-2">
538
+ <input
539
+ type="text"
540
+ value={param.name}
541
+ onChange={(e) => updateParameter(selectedEndpoint.id, param.id, { name: e.target.value })}
542
+ placeholder="Parameter name"
543
+ className="px-2 py-1 border border-gray-300 rounded text-sm"
544
+ />
545
+ <select
546
+ value={param.in}
547
+ onChange={(e) => updateParameter(selectedEndpoint.id, param.id, { in: e.target.value })}
548
+ className="px-2 py-1 border border-gray-300 rounded text-sm"
549
+ >
550
+ <option value="query">Query</option>
551
+ <option value="path">Path</option>
552
+ <option value="header">Header</option>
553
+ </select>
554
+ <select
555
+ value={param.type}
556
+ onChange={(e) => updateParameter(selectedEndpoint.id, param.id, { type: e.target.value })}
557
+ className="px-2 py-1 border border-gray-300 rounded text-sm"
558
+ >
559
+ <option value="string">String</option>
560
+ <option value="number">Number</option>
561
+ <option value="boolean">Boolean</option>
562
+ <option value="array">Array</option>
563
+ </select>
564
+ <div className="flex items-center space-x-2">
565
+ <label className="flex items-center text-sm">
566
+ <input
567
+ type="checkbox"
568
+ checked={param.required}
569
+ onChange={(e) => updateParameter(selectedEndpoint.id, param.id, { required: e.target.checked })}
570
+ className="mr-1"
571
+ />
572
+ Required
573
+ </label>
574
+ <Button
575
+ size="sm"
576
+ variant="outline"
577
+ onClick={() => removeParameter(selectedEndpoint.id, param.id)}
578
+ className="text-red-600"
579
+ >
580
+ ×
581
+ </Button>
582
+ </div>
583
+ </div>
584
+ <input
585
+ type="text"
586
+ value={param.description}
587
+ onChange={(e) => updateParameter(selectedEndpoint.id, param.id, { description: e.target.value })}
588
+ placeholder="Parameter description"
589
+ className="w-full px-2 py-1 border border-gray-300 rounded text-sm"
590
+ />
591
+ </div>
592
+ ))}
593
+ </div>
594
+
595
+ {/* Response Schema */}
596
+ <div>
597
+ <h4 className="font-medium mb-3">Response Schema (200 OK)</h4>
598
+ <SchemaBuilder
599
+ schema={selectedEndpoint.responses?.[200]?.schema || []}
600
+ onChange={(schema) => updateEndpoint(selectedEndpoint.id, {
601
+ responses: {
602
+ ...selectedEndpoint.responses,
603
+ 200: { description: 'Success', schema }
604
+ }
605
+ })}
606
+ />
607
+ </div>
608
+ </div>
609
+ </Card>
610
+ ) : (
611
+ <Card className="p-8">
612
+ <div className="text-center text-gray-500">
613
+ <svg className="w-12 h-12 mx-auto mb-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
614
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z" />
615
+ </svg>
616
+ <p>Select an endpoint to edit its configuration</p>
617
+ <p className="text-sm mt-1">Or create a new endpoint to get started</p>
618
+ </div>
619
+ </Card>
620
+ )}
621
+ </div>
622
+ </div>
623
+
624
+ <div className="flex justify-end">
625
+ <Button
626
+ onClick={handleGenerate}
627
+ disabled={!apiInfo.name || endpoints.length === 0}
628
+ className="bg-green-600 hover:bg-green-700"
629
+ >
630
+ Generate API Code
631
+ </Button>
632
+ </div>
633
+ </div>
634
+ );
635
+ };
636
+
637
+ export default APIEndpointGenerator;