@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,496 +0,0 @@
1
- /**
2
- * DockerAdapter Tests
3
- * Infrastructure adapter for Docker operations - used by pre-flight checks
4
- *
5
- * Tests follow TDD pattern - written BEFORE implementation
6
- */
7
-
8
- // Mock child_process before importing
9
- jest.mock('child_process', () => ({
10
- exec: jest.fn(),
11
- spawn: jest.fn()
12
- }));
13
-
14
- // Mock fs for docker-compose file detection
15
- jest.mock('fs', () => ({
16
- existsSync: jest.fn(),
17
- promises: {
18
- access: jest.fn()
19
- }
20
- }));
21
-
22
- const { exec, spawn } = require('child_process');
23
- const fs = require('fs');
24
- const path = require('path');
25
-
26
- // Import after mocks are set up
27
- const { DockerAdapter } = require('../../../../start-command/infrastructure/DockerAdapter');
28
-
29
- describe('DockerAdapter', () => {
30
- let adapter;
31
-
32
- beforeEach(() => {
33
- jest.clearAllMocks();
34
- adapter = new DockerAdapter();
35
- });
36
-
37
- describe('isDockerInstalled()', () => {
38
- it('should return true when docker CLI is available', async () => {
39
- exec.mockImplementation((cmd, callback) => {
40
- callback(null, 'Docker version 24.0.7, build afdd53b', '');
41
- });
42
-
43
- const result = await adapter.isDockerInstalled();
44
-
45
- expect(result).toBe(true);
46
- expect(exec).toHaveBeenCalledWith('docker --version', expect.any(Function));
47
- });
48
-
49
- it('should return false when docker CLI is not found', async () => {
50
- exec.mockImplementation((cmd, callback) => {
51
- const error = new Error('command not found: docker');
52
- error.code = 127;
53
- callback(error, '', 'command not found: docker');
54
- });
55
-
56
- const result = await adapter.isDockerInstalled();
57
-
58
- expect(result).toBe(false);
59
- });
60
-
61
- it('should return false when docker command fails', async () => {
62
- exec.mockImplementation((cmd, callback) => {
63
- callback(new Error('Docker not installed'), '', '');
64
- });
65
-
66
- const result = await adapter.isDockerInstalled();
67
-
68
- expect(result).toBe(false);
69
- });
70
- });
71
-
72
- describe('isDockerRunning()', () => {
73
- it('should return true when Docker daemon is running', async () => {
74
- exec.mockImplementation((cmd, callback) => {
75
- callback(null, '', '');
76
- });
77
-
78
- const result = await adapter.isDockerRunning();
79
-
80
- expect(result).toBe(true);
81
- expect(exec).toHaveBeenCalledWith('docker info', expect.any(Function));
82
- });
83
-
84
- it('should return false when Docker daemon is not running', async () => {
85
- exec.mockImplementation((cmd, callback) => {
86
- const error = new Error('Cannot connect to the Docker daemon');
87
- callback(error, '', 'Cannot connect to the Docker daemon');
88
- });
89
-
90
- const result = await adapter.isDockerRunning();
91
-
92
- expect(result).toBe(false);
93
- });
94
-
95
- it('should return false when docker info command times out', async () => {
96
- exec.mockImplementation((cmd, callback) => {
97
- const error = new Error('ETIMEDOUT');
98
- error.code = 'ETIMEDOUT';
99
- callback(error, '', '');
100
- });
101
-
102
- const result = await adapter.isDockerRunning();
103
-
104
- expect(result).toBe(false);
105
- });
106
- });
107
-
108
- describe('findDockerComposeFile()', () => {
109
- const projectPath = '/test/project';
110
-
111
- it('should find docker-compose.yml in project root', async () => {
112
- fs.existsSync.mockImplementation((filePath) => {
113
- return filePath === path.join(projectPath, 'docker-compose.yml');
114
- });
115
-
116
- const result = await adapter.findDockerComposeFile(projectPath);
117
-
118
- expect(result).toBe(path.join(projectPath, 'docker-compose.yml'));
119
- });
120
-
121
- it('should find docker-compose.yaml in project root', async () => {
122
- fs.existsSync.mockImplementation((filePath) => {
123
- return filePath === path.join(projectPath, 'docker-compose.yaml');
124
- });
125
-
126
- const result = await adapter.findDockerComposeFile(projectPath);
127
-
128
- expect(result).toBe(path.join(projectPath, 'docker-compose.yaml'));
129
- });
130
-
131
- it('should find compose.yml in project root', async () => {
132
- fs.existsSync.mockImplementation((filePath) => {
133
- return filePath === path.join(projectPath, 'compose.yml');
134
- });
135
-
136
- const result = await adapter.findDockerComposeFile(projectPath);
137
-
138
- expect(result).toBe(path.join(projectPath, 'compose.yml'));
139
- });
140
-
141
- it('should find compose.yaml in project root', async () => {
142
- fs.existsSync.mockImplementation((filePath) => {
143
- return filePath === path.join(projectPath, 'compose.yaml');
144
- });
145
-
146
- const result = await adapter.findDockerComposeFile(projectPath);
147
-
148
- expect(result).toBe(path.join(projectPath, 'compose.yaml'));
149
- });
150
-
151
- it('should return null when no docker-compose file exists', async () => {
152
- fs.existsSync.mockReturnValue(false);
153
-
154
- const result = await adapter.findDockerComposeFile(projectPath);
155
-
156
- expect(result).toBeNull();
157
- });
158
-
159
- it('should prefer docker-compose.yml over other variants', async () => {
160
- // All variants exist
161
- fs.existsSync.mockReturnValue(true);
162
-
163
- const result = await adapter.findDockerComposeFile(projectPath);
164
-
165
- // Should return the first one checked (docker-compose.yml)
166
- expect(result).toBe(path.join(projectPath, 'docker-compose.yml'));
167
- });
168
-
169
- it('should search in parent directory if not found in project path', async () => {
170
- const backendPath = '/test/project/backend';
171
- fs.existsSync.mockImplementation((filePath) => {
172
- // Only exists in parent directory
173
- return filePath === path.join('/test/project', 'docker-compose.yml');
174
- });
175
-
176
- const result = await adapter.findDockerComposeFile(backendPath);
177
-
178
- expect(result).toBe(path.join('/test/project', 'docker-compose.yml'));
179
- });
180
- });
181
-
182
- describe('startDockerCompose()', () => {
183
- const composePath = '/test/project/docker-compose.yml';
184
-
185
- it('should run docker compose up -d successfully', async () => {
186
- exec.mockImplementation((cmd, opts, callback) => {
187
- if (typeof opts === 'function') {
188
- callback = opts;
189
- }
190
- callback(null, 'Container started', '');
191
- });
192
-
193
- const result = await adapter.startDockerCompose(composePath);
194
-
195
- expect(result.success).toBe(true);
196
- expect(exec).toHaveBeenCalledWith(
197
- expect.stringContaining('docker compose'),
198
- expect.any(Object),
199
- expect.any(Function)
200
- );
201
- });
202
-
203
- it('should use correct docker-compose file path', async () => {
204
- exec.mockImplementation((cmd, opts, callback) => {
205
- if (typeof opts === 'function') {
206
- callback = opts;
207
- }
208
- callback(null, '', '');
209
- });
210
-
211
- await adapter.startDockerCompose(composePath);
212
-
213
- expect(exec).toHaveBeenCalledWith(
214
- expect.stringContaining(`-f ${composePath}`),
215
- expect.any(Object),
216
- expect.any(Function)
217
- );
218
- });
219
-
220
- it('should return error when docker compose fails', async () => {
221
- exec.mockImplementation((cmd, opts, callback) => {
222
- if (typeof opts === 'function') {
223
- callback = opts;
224
- }
225
- const error = new Error('Service failed to start');
226
- callback(error, '', 'Service failed to start');
227
- });
228
-
229
- const result = await adapter.startDockerCompose(composePath);
230
-
231
- expect(result.success).toBe(false);
232
- expect(result.error).toContain('Service failed to start');
233
- });
234
-
235
- it('should run in detached mode by default', async () => {
236
- exec.mockImplementation((cmd, opts, callback) => {
237
- if (typeof opts === 'function') {
238
- callback = opts;
239
- }
240
- callback(null, '', '');
241
- });
242
-
243
- await adapter.startDockerCompose(composePath);
244
-
245
- expect(exec).toHaveBeenCalledWith(
246
- expect.stringContaining('up -d'),
247
- expect.any(Object),
248
- expect.any(Function)
249
- );
250
- });
251
-
252
- it('should set working directory to compose file directory', async () => {
253
- exec.mockImplementation((cmd, opts, callback) => {
254
- if (typeof opts === 'function') {
255
- callback = opts;
256
- }
257
- callback(null, '', '');
258
- });
259
-
260
- await adapter.startDockerCompose(composePath);
261
-
262
- expect(exec).toHaveBeenCalledWith(
263
- expect.any(String),
264
- expect.objectContaining({
265
- cwd: path.dirname(composePath)
266
- }),
267
- expect.any(Function)
268
- );
269
- });
270
- });
271
-
272
- describe('stopDockerCompose()', () => {
273
- const composePath = '/test/project/docker-compose.yml';
274
-
275
- it('should run docker compose down successfully', async () => {
276
- exec.mockImplementation((cmd, opts, callback) => {
277
- if (typeof opts === 'function') {
278
- callback = opts;
279
- }
280
- callback(null, 'Containers stopped', '');
281
- });
282
-
283
- const result = await adapter.stopDockerCompose(composePath);
284
-
285
- expect(result.success).toBe(true);
286
- expect(exec).toHaveBeenCalledWith(
287
- expect.stringContaining('docker compose'),
288
- expect.any(Object),
289
- expect.any(Function)
290
- );
291
- expect(exec).toHaveBeenCalledWith(
292
- expect.stringContaining('down'),
293
- expect.any(Object),
294
- expect.any(Function)
295
- );
296
- });
297
-
298
- it('should return error when docker compose down fails', async () => {
299
- exec.mockImplementation((cmd, opts, callback) => {
300
- if (typeof opts === 'function') {
301
- callback = opts;
302
- }
303
- callback(new Error('Failed to stop'), '', 'Failed to stop');
304
- });
305
-
306
- const result = await adapter.stopDockerCompose(composePath);
307
-
308
- expect(result.success).toBe(false);
309
- expect(result.error).toContain('Failed to stop');
310
- });
311
- });
312
-
313
- describe('startDockerDesktop()', () => {
314
- it('should open Docker Desktop on macOS', async () => {
315
- const originalPlatform = process.platform;
316
- Object.defineProperty(process, 'platform', { value: 'darwin' });
317
-
318
- exec.mockImplementation((cmd, callback) => {
319
- callback(null, '', '');
320
- });
321
-
322
- const result = await adapter.startDockerDesktop();
323
-
324
- expect(result.success).toBe(true);
325
- expect(exec).toHaveBeenCalledWith(
326
- expect.stringContaining('open'),
327
- expect.any(Function)
328
- );
329
-
330
- Object.defineProperty(process, 'platform', { value: originalPlatform });
331
- });
332
-
333
- it('should start Docker Desktop on Windows', async () => {
334
- const originalPlatform = process.platform;
335
- Object.defineProperty(process, 'platform', { value: 'win32' });
336
-
337
- exec.mockImplementation((cmd, callback) => {
338
- callback(null, '', '');
339
- });
340
-
341
- const result = await adapter.startDockerDesktop();
342
-
343
- expect(result.success).toBe(true);
344
- expect(exec).toHaveBeenCalledWith(
345
- expect.stringContaining('Docker Desktop'),
346
- expect.any(Function)
347
- );
348
-
349
- Object.defineProperty(process, 'platform', { value: originalPlatform });
350
- });
351
-
352
- it('should start docker service on Linux', async () => {
353
- const originalPlatform = process.platform;
354
- Object.defineProperty(process, 'platform', { value: 'linux' });
355
-
356
- exec.mockImplementation((cmd, callback) => {
357
- callback(null, '', '');
358
- });
359
-
360
- const result = await adapter.startDockerDesktop();
361
-
362
- expect(result.success).toBe(true);
363
- expect(exec).toHaveBeenCalledWith(
364
- expect.stringMatching(/systemctl|service/),
365
- expect.any(Function)
366
- );
367
-
368
- Object.defineProperty(process, 'platform', { value: originalPlatform });
369
- });
370
-
371
- it('should return error when Docker Desktop fails to start', async () => {
372
- exec.mockImplementation((cmd, callback) => {
373
- callback(new Error('Failed to start Docker Desktop'), '', '');
374
- });
375
-
376
- const result = await adapter.startDockerDesktop();
377
-
378
- expect(result.success).toBe(false);
379
- expect(result.error).toBeDefined();
380
- });
381
- });
382
-
383
- describe('getDockerComposeServices()', () => {
384
- const composePath = '/test/project/docker-compose.yml';
385
-
386
- it('should list running services', async () => {
387
- exec.mockImplementation((cmd, opts, callback) => {
388
- if (typeof opts === 'function') {
389
- callback = opts;
390
- }
391
- callback(null, 'mongodb\nredis\n', '');
392
- });
393
-
394
- const result = await adapter.getDockerComposeServices(composePath);
395
-
396
- expect(result).toEqual(['mongodb', 'redis']);
397
- });
398
-
399
- it('should return empty array when no services running', async () => {
400
- exec.mockImplementation((cmd, opts, callback) => {
401
- if (typeof opts === 'function') {
402
- callback = opts;
403
- }
404
- callback(null, '', '');
405
- });
406
-
407
- const result = await adapter.getDockerComposeServices(composePath);
408
-
409
- expect(result).toEqual([]);
410
- });
411
-
412
- it('should handle docker compose ps command failure', async () => {
413
- exec.mockImplementation((cmd, opts, callback) => {
414
- if (typeof opts === 'function') {
415
- callback = opts;
416
- }
417
- callback(new Error('Failed'), '', '');
418
- });
419
-
420
- const result = await adapter.getDockerComposeServices(composePath);
421
-
422
- expect(result).toEqual([]);
423
- });
424
- });
425
-
426
- describe('isServiceRunning()', () => {
427
- const composePath = '/test/project/docker-compose.yml';
428
-
429
- it('should return true when specific service is running', async () => {
430
- exec.mockImplementation((cmd, opts, callback) => {
431
- if (typeof opts === 'function') {
432
- callback = opts;
433
- }
434
- // docker compose ps --services --filter "status=running"
435
- callback(null, 'mongodb\nredis\n', '');
436
- });
437
-
438
- const result = await adapter.isServiceRunning(composePath, 'mongodb');
439
-
440
- expect(result).toBe(true);
441
- });
442
-
443
- it('should return false when service is not running', async () => {
444
- exec.mockImplementation((cmd, opts, callback) => {
445
- if (typeof opts === 'function') {
446
- callback = opts;
447
- }
448
- callback(null, 'redis\n', '');
449
- });
450
-
451
- const result = await adapter.isServiceRunning(composePath, 'mongodb');
452
-
453
- expect(result).toBe(false);
454
- });
455
- });
456
-
457
- describe('waitForDockerReady()', () => {
458
- it('should resolve when Docker becomes ready', async () => {
459
- let callCount = 0;
460
- exec.mockImplementation((cmd, callback) => {
461
- callCount++;
462
- if (callCount >= 3) {
463
- // Docker is ready on third try
464
- callback(null, '', '');
465
- } else {
466
- callback(new Error('Not ready'), '', '');
467
- }
468
- });
469
-
470
- const result = await adapter.waitForDockerReady({ maxAttempts: 5, intervalMs: 10 });
471
-
472
- expect(result).toBe(true);
473
- expect(callCount).toBe(3);
474
- });
475
-
476
- it('should return false after max attempts exceeded', async () => {
477
- exec.mockImplementation((cmd, callback) => {
478
- callback(new Error('Not ready'), '', '');
479
- });
480
-
481
- const result = await adapter.waitForDockerReady({ maxAttempts: 3, intervalMs: 10 });
482
-
483
- expect(result).toBe(false);
484
- });
485
-
486
- it('should use default options when not specified', async () => {
487
- exec.mockImplementation((cmd, callback) => {
488
- callback(null, '', '');
489
- });
490
-
491
- const result = await adapter.waitForDockerReady();
492
-
493
- expect(result).toBe(true);
494
- });
495
- });
496
- });