@friggframework/devtools 2.0.0--canary.522.cbd3d5a.0 → 2.0.0--canary.517.21b69ac.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.
Files changed (247) hide show
  1. package/.eslintrc.json +3 -0
  2. package/CHANGELOG.md +132 -0
  3. package/frigg-cli/README.md +1 -1
  4. package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
  5. package/frigg-cli/__tests__/unit/commands/install.test.js +17 -21
  6. package/frigg-cli/doctor-command/index.js +16 -17
  7. package/frigg-cli/index.js +6 -21
  8. package/frigg-cli/index.test.js +1 -7
  9. package/frigg-cli/init-command/backend-first-handler.js +42 -124
  10. package/frigg-cli/init-command/index.js +1 -2
  11. package/frigg-cli/init-command/template-handler.js +3 -13
  12. package/frigg-cli/install-command/backend-js.js +3 -3
  13. package/frigg-cli/install-command/environment-variables.js +19 -16
  14. package/frigg-cli/install-command/environment-variables.test.js +13 -12
  15. package/frigg-cli/install-command/index.js +9 -14
  16. package/frigg-cli/install-command/integration-file.js +3 -3
  17. package/frigg-cli/install-command/logger.js +12 -0
  18. package/frigg-cli/install-command/validate-package.js +9 -5
  19. package/frigg-cli/jest.config.js +1 -4
  20. package/frigg-cli/repair-command/index.js +128 -101
  21. package/frigg-cli/start-command/index.js +2 -246
  22. package/frigg-cli/ui-command/index.js +36 -58
  23. package/frigg-cli/utils/repo-detection.js +37 -85
  24. package/infrastructure/docs/iam-policy-templates.md +1 -1
  25. package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
  26. package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
  27. package/infrastructure/domains/shared/cloudformation-discovery.test.js +7 -4
  28. package/infrastructure/domains/shared/resource-discovery.js +5 -5
  29. package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
  30. package/infrastructure/domains/shared/utilities/base-definition-factory.js +2 -25
  31. package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
  32. package/infrastructure/infrastructure-composer.test.js +2 -2
  33. package/layers/prisma/.build-complete +3 -0
  34. package/layers/prisma/nodejs/package.json +8 -0
  35. package/management-ui/.eslintrc.js +22 -0
  36. package/management-ui/README.md +109 -245
  37. package/management-ui/components.json +21 -0
  38. package/management-ui/docs/phase2-integration-guide.md +320 -0
  39. package/management-ui/index.html +13 -0
  40. package/management-ui/package.json +76 -0
  41. package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
  42. package/management-ui/postcss.config.js +6 -0
  43. package/management-ui/server/api/backend.js +256 -0
  44. package/management-ui/server/api/cli.js +315 -0
  45. package/management-ui/server/api/codegen.js +663 -0
  46. package/management-ui/server/api/connections.js +857 -0
  47. package/management-ui/server/api/discovery.js +185 -0
  48. package/management-ui/server/api/environment/index.js +1 -0
  49. package/management-ui/server/api/environment/router.js +378 -0
  50. package/management-ui/server/api/environment.js +328 -0
  51. package/management-ui/server/api/integrations.js +876 -0
  52. package/management-ui/server/api/logs.js +248 -0
  53. package/management-ui/server/api/monitoring.js +282 -0
  54. package/management-ui/server/api/open-ide.js +31 -0
  55. package/management-ui/server/api/project.js +1029 -0
  56. package/management-ui/server/api/users/sessions.js +371 -0
  57. package/management-ui/server/api/users/simulation.js +254 -0
  58. package/management-ui/server/api/users.js +362 -0
  59. package/management-ui/server/api-contract.md +275 -0
  60. package/management-ui/server/index.js +873 -0
  61. package/management-ui/server/middleware/errorHandler.js +93 -0
  62. package/management-ui/server/middleware/security.js +32 -0
  63. package/management-ui/server/processManager.js +296 -0
  64. package/management-ui/server/server.js +346 -0
  65. package/management-ui/server/services/aws-monitor.js +413 -0
  66. package/management-ui/server/services/npm-registry.js +347 -0
  67. package/management-ui/server/services/template-engine.js +538 -0
  68. package/management-ui/server/utils/cliIntegration.js +220 -0
  69. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  70. package/management-ui/server/utils/environment/awsParameterStore.js +275 -0
  71. package/management-ui/server/utils/environment/encryption.js +278 -0
  72. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  73. package/management-ui/server/utils/import-commonjs.js +28 -0
  74. package/management-ui/server/utils/response.js +83 -0
  75. package/management-ui/server/websocket/handler.js +325 -0
  76. package/management-ui/src/App.jsx +25 -0
  77. package/management-ui/src/assets/FriggLogo.svg +1 -0
  78. package/management-ui/src/components/AppRouter.jsx +65 -0
  79. package/management-ui/src/components/Button.jsx +70 -0
  80. package/management-ui/src/components/Card.jsx +97 -0
  81. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  82. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  83. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  84. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  85. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  86. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  87. package/management-ui/src/components/IntegrationCard.jsx +481 -0
  88. package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
  89. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  90. package/management-ui/src/components/IntegrationStatus.jsx +336 -0
  91. package/management-ui/src/components/Layout.jsx +716 -0
  92. package/management-ui/src/components/LoadingSpinner.jsx +113 -0
  93. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  94. package/management-ui/src/components/SessionMonitor.jsx +350 -0
  95. package/management-ui/src/components/StatusBadge.jsx +208 -0
  96. package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
  97. package/management-ui/src/components/UserSimulation.jsx +327 -0
  98. package/management-ui/src/components/Welcome.jsx +434 -0
  99. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  100. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  101. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  102. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  103. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  104. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  105. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  106. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  107. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  108. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  109. package/management-ui/src/components/codegen/index.js +10 -0
  110. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  111. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  112. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  113. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  114. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  115. package/management-ui/src/components/connections/index.js +5 -0
  116. package/management-ui/src/components/index.js +21 -0
  117. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  118. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  119. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  120. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  121. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  122. package/management-ui/src/components/monitoring/index.js +6 -0
  123. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  124. package/management-ui/src/components/theme-provider.jsx +52 -0
  125. package/management-ui/src/components/theme-toggle.jsx +39 -0
  126. package/management-ui/src/components/ui/badge.tsx +36 -0
  127. package/management-ui/src/components/ui/button.test.jsx +56 -0
  128. package/management-ui/src/components/ui/button.tsx +57 -0
  129. package/management-ui/src/components/ui/card.tsx +76 -0
  130. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  131. package/management-ui/src/components/ui/select.tsx +157 -0
  132. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  133. package/management-ui/src/hooks/useFrigg.jsx +387 -0
  134. package/management-ui/src/hooks/useSocket.jsx +58 -0
  135. package/management-ui/src/index.css +193 -0
  136. package/management-ui/src/lib/utils.ts +6 -0
  137. package/management-ui/src/main.jsx +10 -0
  138. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  139. package/management-ui/src/pages/Connections.jsx +252 -0
  140. package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
  141. package/management-ui/src/pages/Dashboard.jsx +311 -0
  142. package/management-ui/src/pages/Environment.jsx +314 -0
  143. package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
  144. package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
  145. package/management-ui/src/pages/IntegrationTest.jsx +742 -0
  146. package/management-ui/src/pages/Integrations.jsx +253 -0
  147. package/management-ui/src/pages/Monitoring.jsx +17 -0
  148. package/management-ui/src/pages/Simulation.jsx +155 -0
  149. package/management-ui/src/pages/Users.jsx +492 -0
  150. package/management-ui/src/services/api.js +41 -0
  151. package/management-ui/src/services/apiModuleService.js +193 -0
  152. package/management-ui/src/services/websocket-handlers.js +120 -0
  153. package/management-ui/src/test/api/project.test.js +273 -0
  154. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  155. package/management-ui/src/test/mocks/server.js +178 -0
  156. package/management-ui/src/test/setup.js +61 -0
  157. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  158. package/management-ui/src/utils/repository.js +98 -0
  159. package/management-ui/src/utils/repository.test.js +118 -0
  160. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  161. package/management-ui/tailwind.config.js +63 -0
  162. package/management-ui/tsconfig.json +37 -0
  163. package/management-ui/tsconfig.node.json +10 -0
  164. package/management-ui/vite.config.js +26 -0
  165. package/management-ui/vitest.config.js +38 -0
  166. package/package.json +7 -17
  167. package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
  168. package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
  169. package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
  170. package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
  171. package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
  172. package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
  173. package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
  174. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
  175. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
  176. package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -430
  177. package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
  178. package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
  179. package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
  180. package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
  181. package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
  182. package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
  183. package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
  184. package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
  185. package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
  186. package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
  187. package/frigg-cli/container.js +0 -172
  188. package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
  189. package/frigg-cli/domain/entities/ApiModule.js +0 -272
  190. package/frigg-cli/domain/entities/AppDefinition.js +0 -227
  191. package/frigg-cli/domain/entities/Integration.js +0 -198
  192. package/frigg-cli/domain/exceptions/DomainException.js +0 -24
  193. package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
  194. package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
  195. package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
  196. package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
  197. package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
  198. package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
  199. package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
  200. package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
  201. package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
  202. package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
  203. package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
  204. package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
  205. package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
  206. package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
  207. package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
  208. package/frigg-cli/package-lock.json +0 -16226
  209. package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
  210. package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
  211. package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
  212. package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
  213. package/frigg-cli/templates/backend/.env.example +0 -62
  214. package/frigg-cli/templates/backend/.eslintrc.json +0 -12
  215. package/frigg-cli/templates/backend/.prettierrc +0 -6
  216. package/frigg-cli/templates/backend/docker-compose.yml +0 -22
  217. package/frigg-cli/templates/backend/index.js +0 -96
  218. package/frigg-cli/templates/backend/infrastructure.js +0 -12
  219. package/frigg-cli/templates/backend/jest.config.js +0 -17
  220. package/frigg-cli/templates/backend/package.json +0 -50
  221. package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
  222. package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
  223. package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
  224. package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
  225. package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
  226. package/frigg-cli/templates/backend/test/setup.js +0 -30
  227. package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
  228. package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
  229. package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
  230. package/frigg-cli/utils/output.js +0 -382
  231. package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
  232. package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
  233. package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
  234. package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
  235. package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
  236. package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
  237. package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
  238. package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
  239. package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
  240. package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
  241. package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
  242. package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
  243. package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
  244. package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
  245. package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
  246. package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
  247. package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
@@ -1,306 +0,0 @@
1
- /**
2
- * DockerAdapter - Infrastructure adapter for Docker operations
3
- *
4
- * Provides methods to interact with Docker and Docker Compose
5
- * Used by pre-flight checks to verify database infrastructure is ready
6
- */
7
-
8
- const { exec } = require('child_process');
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- class DockerAdapter {
13
- /**
14
- * Check if Docker CLI is installed
15
- * @returns {Promise<boolean>} True if docker command is available
16
- */
17
- async isDockerInstalled() {
18
- return new Promise((resolve) => {
19
- exec('docker --version', (error) => {
20
- resolve(!error);
21
- });
22
- });
23
- }
24
-
25
- /**
26
- * Check if Docker daemon is running
27
- * @returns {Promise<boolean>} True if docker daemon is responsive
28
- */
29
- async isDockerRunning() {
30
- return new Promise((resolve) => {
31
- exec('docker info', (error) => {
32
- resolve(!error);
33
- });
34
- });
35
- }
36
-
37
- /**
38
- * Find docker-compose file in project directory or parent
39
- * @param {string} projectPath - Path to search in
40
- * @returns {Promise<string|null>} Path to compose file or null if not found
41
- */
42
- async findDockerComposeFile(projectPath) {
43
- const composeFileNames = [
44
- 'docker-compose.yml',
45
- 'docker-compose.yaml',
46
- 'compose.yml',
47
- 'compose.yaml'
48
- ];
49
-
50
- // Search in project path first
51
- for (const fileName of composeFileNames) {
52
- const filePath = path.join(projectPath, fileName);
53
- if (fs.existsSync(filePath)) {
54
- return filePath;
55
- }
56
- }
57
-
58
- // Search in parent directory (for backend paths)
59
- const parentPath = path.dirname(projectPath);
60
- if (parentPath !== projectPath) {
61
- for (const fileName of composeFileNames) {
62
- const filePath = path.join(parentPath, fileName);
63
- if (fs.existsSync(filePath)) {
64
- return filePath;
65
- }
66
- }
67
- }
68
-
69
- return null;
70
- }
71
-
72
- /**
73
- * Start Docker Compose services
74
- * @param {string} composePath - Path to docker-compose file
75
- * @returns {Promise<{success: boolean, error?: string, output?: string}>}
76
- */
77
- async startDockerCompose(composePath) {
78
- return new Promise((resolve) => {
79
- const cmd = `docker compose -f ${composePath} up -d`;
80
- const options = { cwd: path.dirname(composePath) };
81
-
82
- exec(cmd, options, (error, stdout, stderr) => {
83
- if (error) {
84
- resolve({
85
- success: false,
86
- error: stderr || error.message
87
- });
88
- } else {
89
- resolve({
90
- success: true,
91
- output: stdout
92
- });
93
- }
94
- });
95
- });
96
- }
97
-
98
- /**
99
- * Stop Docker Compose services
100
- * @param {string} composePath - Path to docker-compose file
101
- * @returns {Promise<{success: boolean, error?: string, output?: string}>}
102
- */
103
- async stopDockerCompose(composePath) {
104
- return new Promise((resolve) => {
105
- const cmd = `docker compose -f ${composePath} down`;
106
- const options = { cwd: path.dirname(composePath) };
107
-
108
- exec(cmd, options, (error, stdout, stderr) => {
109
- if (error) {
110
- resolve({
111
- success: false,
112
- error: stderr || error.message
113
- });
114
- } else {
115
- resolve({
116
- success: true,
117
- output: stdout
118
- });
119
- }
120
- });
121
- });
122
- }
123
-
124
- /**
125
- * Start Docker Desktop application
126
- * @returns {Promise<{success: boolean, error?: string}>}
127
- */
128
- async startDockerDesktop() {
129
- return new Promise((resolve) => {
130
- let cmd;
131
- const platform = process.platform;
132
-
133
- if (platform === 'darwin') {
134
- cmd = 'open -a "Docker Desktop"';
135
- } else if (platform === 'win32') {
136
- cmd = 'start "" "C:\\Program Files\\Docker\\Docker\\Docker Desktop.exe"';
137
- } else {
138
- // Linux - try systemctl first, fall back to service
139
- cmd = 'systemctl start docker || service docker start';
140
- }
141
-
142
- exec(cmd, (error) => {
143
- if (error) {
144
- resolve({
145
- success: false,
146
- error: error.message
147
- });
148
- } else {
149
- resolve({ success: true });
150
- }
151
- });
152
- });
153
- }
154
-
155
- /**
156
- * Get list of running Docker Compose services
157
- * @param {string} composePath - Path to docker-compose file
158
- * @returns {Promise<string[]>} List of running service names
159
- */
160
- async getDockerComposeServices(composePath) {
161
- return new Promise((resolve) => {
162
- const cmd = `docker compose -f ${composePath} ps --services --filter "status=running"`;
163
- const options = { cwd: path.dirname(composePath) };
164
-
165
- exec(cmd, options, (error, stdout) => {
166
- if (error) {
167
- resolve([]);
168
- } else {
169
- const services = stdout
170
- .split('\n')
171
- .map(s => s.trim())
172
- .filter(s => s.length > 0);
173
- resolve(services);
174
- }
175
- });
176
- });
177
- }
178
-
179
- /**
180
- * Check if a specific service is running
181
- * @param {string} composePath - Path to docker-compose file
182
- * @param {string} serviceName - Name of the service to check
183
- * @returns {Promise<boolean>} True if service is running
184
- */
185
- async isServiceRunning(composePath, serviceName) {
186
- const services = await this.getDockerComposeServices(composePath);
187
- return services.includes(serviceName);
188
- }
189
-
190
- /**
191
- * Wait for Docker to become ready after starting
192
- * @param {object} options - Wait options
193
- * @param {number} options.maxAttempts - Maximum number of attempts (default: 30)
194
- * @param {number} options.intervalMs - Interval between attempts in ms (default: 1000)
195
- * @returns {Promise<boolean>} True if Docker became ready, false if timed out
196
- */
197
- async waitForDockerReady(options = {}) {
198
- const { maxAttempts = 30, intervalMs = 1000 } = options;
199
-
200
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
201
- const isRunning = await this.isDockerRunning();
202
- if (isRunning) {
203
- return true;
204
- }
205
- await this._sleep(intervalMs);
206
- }
207
-
208
- return false;
209
- }
210
-
211
- /**
212
- * Wait for LocalStack to be ready by polling health endpoint
213
- * @param {object} options - Wait options
214
- * @param {number} options.maxAttempts - Maximum number of attempts (default: 30)
215
- * @param {number} options.intervalMs - Interval between attempts in ms (default: 2000)
216
- * @param {string} options.endpoint - LocalStack endpoint (default: http://localhost:4566)
217
- * @returns {Promise<{ready: boolean, services?: object, error?: string}>}
218
- */
219
- async waitForLocalStack(options = {}) {
220
- const {
221
- maxAttempts = 30,
222
- intervalMs = 2000,
223
- endpoint = process.env.AWS_ENDPOINT || 'http://localhost:4566'
224
- } = options;
225
-
226
- const healthUrl = `${endpoint}/_localstack/health`;
227
-
228
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
229
- try {
230
- const result = await this._checkLocalStackHealth(healthUrl);
231
- if (result.ready) {
232
- return result;
233
- }
234
- // Not ready yet, wait and retry
235
- if (attempt < maxAttempts) {
236
- await this._sleep(intervalMs);
237
- }
238
- } catch (error) {
239
- // Connection failed, wait and retry
240
- if (attempt < maxAttempts) {
241
- await this._sleep(intervalMs);
242
- }
243
- }
244
- }
245
-
246
- return {
247
- ready: false,
248
- error: `LocalStack not ready after ${maxAttempts} attempts`
249
- };
250
- }
251
-
252
- /**
253
- * Check LocalStack health endpoint
254
- * @param {string} healthUrl - URL to health endpoint
255
- * @returns {Promise<{ready: boolean, services?: object}>}
256
- */
257
- async _checkLocalStackHealth(healthUrl) {
258
- return new Promise((resolve, reject) => {
259
- const http = require('http');
260
- const url = new URL(healthUrl);
261
-
262
- const req = http.get({
263
- hostname: url.hostname,
264
- port: url.port,
265
- path: url.pathname,
266
- timeout: 5000
267
- }, (res) => {
268
- let data = '';
269
- res.on('data', chunk => data += chunk);
270
- res.on('end', () => {
271
- try {
272
- const health = JSON.parse(data);
273
- // Check if services are running
274
- // LocalStack returns: { "services": { "sqs": "running", ... } }
275
- const services = health.services || {};
276
- const sqsReady = services.sqs === 'running' || services.sqs === 'available';
277
-
278
- resolve({
279
- ready: sqsReady,
280
- services: services
281
- });
282
- } catch (e) {
283
- resolve({ ready: false });
284
- }
285
- });
286
- });
287
-
288
- req.on('error', reject);
289
- req.on('timeout', () => {
290
- req.destroy();
291
- reject(new Error('Timeout'));
292
- });
293
- });
294
- }
295
-
296
- /**
297
- * Helper to sleep for specified milliseconds
298
- * @param {number} ms - Milliseconds to sleep
299
- * @returns {Promise<void>}
300
- */
301
- _sleep(ms) {
302
- return new Promise(resolve => setTimeout(resolve, ms));
303
- }
304
- }
305
-
306
- module.exports = { DockerAdapter };
@@ -1,329 +0,0 @@
1
- /**
2
- * InteractivePromptAdapter - Handles prompts in terminal mode or IPC mode
3
- *
4
- * Presentation Layer - Adapts prompt interfaces for different contexts:
5
- * - Terminal mode: Uses @inquirer/prompts for direct CLI interaction
6
- * - IPC mode: Outputs JSON to stdout and reads responses from stdin
7
- * (used when Management UI spawns the CLI process)
8
- */
9
-
10
- const { confirm, select, input } = require('@inquirer/prompts');
11
- const { randomUUID } = require('crypto');
12
-
13
- /**
14
- * Factory for creating the appropriate prompt adapter
15
- */
16
- class InteractivePromptAdapter {
17
- /**
18
- * Create a prompt adapter based on mode
19
- * @param {object} options - Options
20
- * @param {string} options.mode - 'terminal' or 'ipc'
21
- * @returns {TerminalPromptAdapter|IpcPromptAdapter}
22
- */
23
- static create(options = {}) {
24
- // Check for IPC mode via environment variable or explicit option
25
- const isIpcMode = options.mode === 'ipc' || process.env.FRIGG_IPC === 'true';
26
-
27
- if (isIpcMode) {
28
- return new IpcPromptAdapter();
29
- }
30
-
31
- return new TerminalPromptAdapter();
32
- }
33
- }
34
-
35
- /**
36
- * Terminal-based prompt adapter using @inquirer/prompts
37
- */
38
- class TerminalPromptAdapter {
39
- /**
40
- * Show a confirmation prompt
41
- * @param {object} options - Prompt options
42
- * @param {string} options.message - Prompt message
43
- * @param {boolean} options.default - Default value
44
- * @returns {Promise<boolean>}
45
- */
46
- async confirm(options) {
47
- return confirm({
48
- message: options.message,
49
- default: options.default
50
- });
51
- }
52
-
53
- /**
54
- * Show a selection prompt
55
- * @param {object} options - Prompt options
56
- * @param {string} options.message - Prompt message
57
- * @param {Array} options.choices - Array of {value, name} choices
58
- * @returns {Promise<string>}
59
- */
60
- async select(options) {
61
- return select({
62
- message: options.message,
63
- choices: options.choices
64
- });
65
- }
66
-
67
- /**
68
- * Show a text input prompt
69
- * @param {object} options - Prompt options
70
- * @param {string} options.message - Prompt message
71
- * @param {string} options.default - Default value
72
- * @returns {Promise<string>}
73
- */
74
- async input(options) {
75
- return input({
76
- message: options.message,
77
- default: options.default
78
- });
79
- }
80
-
81
- /**
82
- * Prompt user to resolve a failed pre-flight check
83
- * @param {object} check - Pre-flight check result
84
- * @returns {Promise<{shouldResolve: boolean, composePath?: string}>}
85
- */
86
- async promptForResolution(check) {
87
- if (!check.canResolve) {
88
- return { shouldResolve: false };
89
- }
90
-
91
- const shouldResolve = await this.confirm({
92
- message: check.resolution.prompt,
93
- default: true
94
- });
95
-
96
- const result = { shouldResolve };
97
-
98
- if (check.resolution.composePath) {
99
- result.composePath = check.resolution.composePath;
100
- }
101
-
102
- return result;
103
- }
104
- }
105
-
106
- /**
107
- * IPC-based prompt adapter for Management UI integration
108
- * Outputs JSON prompts to stdout, reads responses from stdin
109
- */
110
- class IpcPromptAdapter {
111
- constructor() {
112
- this._pendingPrompts = new Map();
113
- this._stdinBuffer = '';
114
- this._stdinListenerSetup = false;
115
- }
116
-
117
- /**
118
- * Setup stdin listener for IPC responses (lazy initialization)
119
- */
120
- _setupStdinListener() {
121
- if (this._stdinListenerSetup) return;
122
- this._stdinListenerSetup = true;
123
-
124
- process.stdin.setEncoding('utf8');
125
- process.stdin.on('data', (chunk) => {
126
- this._stdinBuffer += chunk;
127
-
128
- // Process complete lines
129
- const lines = this._stdinBuffer.split('\n');
130
- this._stdinBuffer = lines.pop(); // Keep incomplete line in buffer
131
-
132
- for (const line of lines) {
133
- if (!line.trim()) continue;
134
-
135
- const ipcMessage = this._parseIpcMessage(line);
136
- if (ipcMessage && ipcMessage.type === 'prompt_response') {
137
- this._resolvePrompt(ipcMessage.requestId, ipcMessage.response);
138
- }
139
- }
140
- });
141
-
142
- process.stdin.on('end', () => {
143
- // stdin closed - resolve any pending prompts with default/false
144
- for (const [requestId, resolver] of this._pendingPrompts) {
145
- resolver(false);
146
- }
147
- this._pendingPrompts.clear();
148
- });
149
-
150
- // Resume stdin to start receiving data
151
- process.stdin.resume();
152
- }
153
-
154
- /**
155
- * Generate a unique request ID
156
- * @returns {string}
157
- */
158
- _generateRequestId() {
159
- return `prompt-${randomUUID().split('-')[0]}`;
160
- }
161
-
162
- /**
163
- * Format IPC output message
164
- * @param {string} type - Message type
165
- * @param {object} data - Message data
166
- * @returns {string} JSON string with newline
167
- */
168
- _formatIpcOutput(type, data) {
169
- const message = {
170
- frigg_ipc: type,
171
- ...data
172
- };
173
- return JSON.stringify(message) + '\n';
174
- }
175
-
176
- /**
177
- * Parse an IPC message from stdin
178
- * @param {string} message - Raw message string
179
- * @returns {object|null} Parsed message or null if not IPC
180
- */
181
- _parseIpcMessage(message) {
182
- try {
183
- const parsed = JSON.parse(message);
184
- if (!parsed.frigg_ipc) {
185
- return null;
186
- }
187
- return {
188
- type: parsed.frigg_ipc,
189
- requestId: parsed.requestId,
190
- response: parsed.response
191
- };
192
- } catch {
193
- return null;
194
- }
195
- }
196
-
197
- /**
198
- * Resolve a pending prompt with a response
199
- * @param {string} requestId - Request ID
200
- * @param {any} response - Response value
201
- */
202
- _resolvePrompt(requestId, response) {
203
- const resolver = this._pendingPrompts.get(requestId);
204
- if (resolver) {
205
- resolver(response);
206
- this._pendingPrompts.delete(requestId);
207
- }
208
- }
209
-
210
- /**
211
- * Handle a response from the Management UI
212
- * @param {string} requestId - Request ID
213
- * @param {any} response - Response value
214
- */
215
- handleResponse(requestId, response) {
216
- this._resolvePrompt(requestId, response);
217
- }
218
-
219
- /**
220
- * Show a confirmation prompt via IPC
221
- * @param {object} options - Prompt options
222
- * @returns {Promise<boolean>}
223
- */
224
- async confirm(options) {
225
- // Setup stdin listener before sending prompt
226
- this._setupStdinListener();
227
-
228
- const requestId = this._generateRequestId();
229
-
230
- const output = this._formatIpcOutput('prompt_request', {
231
- requestId,
232
- prompt: {
233
- type: 'confirm',
234
- message: options.message,
235
- default: options.default
236
- }
237
- });
238
-
239
- process.stdout.write(output);
240
-
241
- return new Promise((resolve) => {
242
- this._pendingPrompts.set(requestId, resolve);
243
- });
244
- }
245
-
246
- /**
247
- * Show a selection prompt via IPC
248
- * @param {object} options - Prompt options
249
- * @returns {Promise<string>}
250
- */
251
- async select(options) {
252
- // Setup stdin listener before sending prompt
253
- this._setupStdinListener();
254
-
255
- const requestId = this._generateRequestId();
256
-
257
- const output = this._formatIpcOutput('prompt_request', {
258
- requestId,
259
- prompt: {
260
- type: 'select',
261
- message: options.message,
262
- choices: options.choices
263
- }
264
- });
265
-
266
- process.stdout.write(output);
267
-
268
- return new Promise((resolve) => {
269
- this._pendingPrompts.set(requestId, resolve);
270
- });
271
- }
272
-
273
- /**
274
- * Show a text input prompt via IPC
275
- * @param {object} options - Prompt options
276
- * @returns {Promise<string>}
277
- */
278
- async input(options) {
279
- // Setup stdin listener before sending prompt
280
- this._setupStdinListener();
281
-
282
- const requestId = this._generateRequestId();
283
-
284
- const output = this._formatIpcOutput('prompt_request', {
285
- requestId,
286
- prompt: {
287
- type: 'input',
288
- message: options.message,
289
- default: options.default
290
- }
291
- });
292
-
293
- process.stdout.write(output);
294
-
295
- return new Promise((resolve) => {
296
- this._pendingPrompts.set(requestId, resolve);
297
- });
298
- }
299
-
300
- /**
301
- * Prompt user to resolve a failed pre-flight check via IPC
302
- * @param {object} check - Pre-flight check result
303
- * @returns {Promise<{shouldResolve: boolean, composePath?: string}>}
304
- */
305
- async promptForResolution(check) {
306
- if (!check.canResolve) {
307
- return { shouldResolve: false };
308
- }
309
-
310
- const shouldResolve = await this.confirm({
311
- message: check.resolution.prompt,
312
- default: true
313
- });
314
-
315
- const result = { shouldResolve };
316
-
317
- if (check.resolution.composePath) {
318
- result.composePath = check.resolution.composePath;
319
- }
320
-
321
- return result;
322
- }
323
- }
324
-
325
- module.exports = {
326
- InteractivePromptAdapter,
327
- TerminalPromptAdapter,
328
- IpcPromptAdapter
329
- };
@@ -1,62 +0,0 @@
1
- # Frigg Backend Environment Variables
2
- # Copy this file to .env and fill in your values
3
- # Or use the default .env file included with the project
4
-
5
- # ============================================================================
6
- # Core Configuration
7
- # ============================================================================
8
- FRIGG_BASE_URL=http://localhost:3001
9
- REDIRECT_URI=http://localhost:3000/redirect
10
-
11
- # Stage (local, dev, test, staging, production)
12
- STAGE=local
13
-
14
- # ============================================================================
15
- # Database Configuration
16
- # ============================================================================
17
- # PostgreSQL (default for new projects - used with Docker)
18
- DATABASE_URL=postgresql://frigg:frigg@localhost:5432/frigg
19
- DATABASE_USER=frigg
20
- DATABASE_PASSWORD=frigg
21
-
22
- # MongoDB (alternative - uncomment if using MongoDB)
23
- # MONGO_URI=mongodb://127.0.0.1:27017/frigg
24
-
25
- # ============================================================================
26
- # Security Keys
27
- # ============================================================================
28
- # Admin API key for management UI auto-connect (REQUIRED for admin features)
29
- # Generate a secure random string for production
30
- FRIGG_ADMIN_API_KEY=dev-admin-key-change-in-production
31
-
32
- # Shared secret API key for header-based authentication (optional)
33
- # Used when userManagementMode.sharedSecretEnabled is true
34
- FRIGG_API_KEY=dev-shared-secret-change-in-production
35
-
36
- # Health check API key (optional - for protected health endpoints)
37
- HEALTH_API_KEY=dev-health-key
38
-
39
- # ============================================================================
40
- # Encryption Configuration
41
- # ============================================================================
42
- # AES encryption (for local development - simpler setup)
43
- AES_KEY_ID=local-dev-key
44
- AES_KEY=32-character-secret-key-here-!!
45
-
46
- # AWS KMS encryption (for production - comment out AES and use these)
47
- # KMS_KEY_ARN=arn:aws:kms:us-east-1:123456789012:key/your-key-id
48
-
49
- # ============================================================================
50
- # AWS Configuration (for deployment)
51
- # ============================================================================
52
- AWS_REGION=us-east-1
53
- # S3_BUCKET_NAME=your-s3-bucket
54
-
55
- # ============================================================================
56
- # Integration Credentials
57
- # ============================================================================
58
- # Add your integration-specific credentials below
59
- # HUBSPOT_CLIENT_ID=
60
- # HUBSPOT_CLIENT_SECRET=
61
- # SALESFORCE_CLIENT_ID=
62
- # SALESFORCE_CLIENT_SECRET=
@@ -1,12 +0,0 @@
1
- {
2
- "extends": ["@friggframework/eslint-config"],
3
- "env": {
4
- "node": true,
5
- "jest": true,
6
- "es2021": true
7
- },
8
- "parserOptions": {
9
- "ecmaVersion": 2021
10
- },
11
- "rules": {}
12
- }